Python asyncio中await Future疑似阻塞问题及替代方案咨询
问题分析与解决方案
问题根源:不是GIL的问题,是代码逻辑和API使用错误
你的代码问题和GIL完全无关,核心错误有三个:
- 任务执行顺序颠倒:你先
await wait_on_data(fut),此时Future还未被设置结果,wait_on_data会一直等待直到超时;等超时返回后才提交set_status执行,这时候已经来不及设置Future结果了。 run_in_executor使用错误:run_in_executor需要传入可调用对象和参数,你直接调用set_status(fut)会导致函数立即执行(且此时已经超时),而非提交到线程池异步执行。正确用法是run_in_executor(None, set_status, fut),第一个参数为None表示使用默认线程池。- 断言逻辑错误:
wait_on_data返回的是元组(True, True)或(False, False),但你断言result == True,这永远会失败,因为元组和布尔值不相等。
修正后的代码示例
方案1:用线程池执行同步函数set_status
import asyncio def set_status(fut): print("set future") fut.set_result((True, True)) async def wait_on_data(fut): try: async with asyncio.timeout(10): print("waiting for future") await fut return fut.result() except TimeoutError: print("timeout for future") return (False, False) async def main(): loop = asyncio.get_running_loop() fut = loop.create_future() # 先提交set_status到线程池异步执行,再等待Future结果 await loop.run_in_executor(None, set_status, fut) result = await wait_on_data(fut) # 修正断言逻辑 assert result == (True, True), "Result mismatch" print("Success, result:", result) asyncio.run(main())
方案2:改为异步函数用create_task调度
如果set_status本身不需要阻塞线程(仅处理异步逻辑),可以改成异步函数,用asyncio.create_task直接调度:
import asyncio async def set_status(fut): print("set future") fut.set_result((True, True)) async def wait_on_data(fut): try: async with asyncio.timeout(10): print("waiting for future") await fut return fut.result() except TimeoutError: print("timeout for future") return (False, False) async def main(): fut = asyncio.get_running_loop().create_future() # 创建异步任务并立即调度 asyncio.create_task(set_status(fut)) result = await wait_on_data(fut) assert result == (True, True), "Result mismatch" print("Success, result:", result) asyncio.run(main())
关键说明
- 异步编程核心是先调度任务,再等待结果,不能先等待再调度,否则必然超时。
run_in_executor用于将同步阻塞函数放到线程池执行,避免阻塞事件循环;纯异步逻辑直接用create_task更高效。- Future的
set_result是线程安全的,不管在事件循环线程还是线程池里调用都能正确设置结果。
内容的提问来源于stack exchange,提问作者zzcc0909
相关产品推荐
相关产品推荐

