Python中如何将同步调用等待的代码修改成异步执行
Python 程序调用了一些 c++导出的函数,这些函数大多会访问网络,会阻塞等待。
因为一些原因,现在无法修改那部分代码,所以我考虑用 thread / gevent 来在 python 里面实现异步操作。
直接把处理函数丢给 thread/gevent 里面去处理,这样主线程 UI 也不会阻塞住,在处理完成后,通知主线程去处理数据结果。
对 Python 不熟,请问有什么更好的方法吗?
Python中如何将同步调用等待的代码修改成异步执行
1.C 代码是用不了 gevent 的。 gevent 是套住 Python 的 IO 操作
2.thread 大概没问题
import asyncio
import time
# 原始同步代码
def sync_task(name: str, delay: int):
"""模拟耗时同步任务"""
print(f"{name}: 开始执行,需要{delay}秒")
time.sleep(delay) # 同步阻塞
print(f"{name}: 执行完成")
return f"{name}的结果"
# 修改后的异步版本
async def async_task(name: str, delay: int):
"""异步版本的任务"""
print(f"{name}: 开始执行,需要{delay}秒")
await asyncio.sleep(delay) # 异步等待,不阻塞事件循环
print(f"{name}: 执行完成")
return f"{name}的结果"
# 同步执行示例(串行)
def sync_main():
start = time.time()
result1 = sync_task("任务1", 2)
result2 = sync_task("任务2", 1)
print(f"同步执行结果: {result1}, {result2}")
print(f"总耗时: {time.time() - start:.2f}秒")
# 异步执行示例(并发)
async def async_main():
start = time.time()
# 创建两个并发任务
task1 = asyncio.create_task(async_task("任务1", 2))
task2 = asyncio.create_task(async_task("任务2", 1))
# 等待所有任务完成
result1 = await task1
result2 = await task2
print(f"异步执行结果: {result1}, {result2}")
print(f"总耗时: {time.time() - start:.2f}秒")
# 运行对比
if __name__ == "__main__":
print("=== 同步执行 ===")
sync_main() # 总耗时约3秒
print("\n=== 异步执行 ===")
asyncio.run(async_main()) # 总耗时约2秒(并发执行)
核心修改点:
- 函数定义:在
def前加async关键字声明异步函数 - 阻塞调用替换:将
time.sleep()换成await asyncio.sleep() - 执行方式:使用
asyncio.create_task()创建并发任务,用await等待结果 - 入口点:通过
asyncio.run()启动异步主函数
关键区别:
- 同步代码中
time.sleep(2)会阻塞整个线程2秒 - 异步代码中
await asyncio.sleep(2)只会暂停当前协程,事件循环可以继续执行其他任务
适用场景:
- I/O密集型操作(网络请求、文件读写、数据库查询)
- 需要同时处理多个耗时操作
- Web服务器、爬虫等并发场景
一句话总结:把阻塞调用换成awaitable对象,用asyncio管理并发。
豆瓣开源了一个叫 greenify 的项目,直接二进制打 patch,你可以试一试
如果导出函数不是异步操作 Gevent 管不了,想要解决这个只能用 C 去 call Gevent 的 API
用 Cython nogil 模式调用 C++ 函数,然后在 Python 这边可以用 threading 来调用这个 Cython wrapper
Using C++ in Cython : http://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html
Releasing the GIL : http://docs.cython.org/en/latest/src/userguide/external_C_code.html#nogil


