如何超时asyncio.to_thread?
How to timeout asyncio.to_thread?
我在 Python 3.9 中对 new asyncio features 进行了试验,得到了以下代码:
import asyncio
async def inc(start):
i = start
while True:
print(i)
i += 2
return None
async def main():
x = asyncio.gather(
asyncio.to_thread(inc, 0),
asyncio.to_thread(inc, 1)
)
try:
await asyncio.wait_for(x, timeout=5.0)
except asyncio.TimeoutError:
print("timeout!")
asyncio.run(main())
我的期望是该程序将从 0
开始打印数字并在 5 秒后终止。但是,当我执行程序 here 时,我没有看到任何输出和以下警告:
/usr/lib/python3.9/asyncio/events.py:80: RuntimeWarning: coroutine 'inc' was never awaited
self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/usr/lib/python3.9/concurrent/futures/thread.py:85: RuntimeWarning: coroutine 'inc' was never awaited
del work_item
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
asyncio.to_thread 将 常规 函数转换为协程。
您只需将 async def inc
更改为 def inc
。可以这样做,因为没有await
,不是真正的协程
但是,您不能终止线程。超时会导致停止等待,而不是停止计算数字。
更新:详细来说,asyncio.gather
等待协程直到超时。当超时取消时,gather
取消所有仍然 运行 协程 a 并等待它们终止。取消协程意味着在最近的 await
语句处传递异常。在这种情况下,没有 await
并且协程永远不会收到取消异常。程序在那一点挂起。
我在 Python 3.9 中对 new asyncio features 进行了试验,得到了以下代码:
import asyncio
async def inc(start):
i = start
while True:
print(i)
i += 2
return None
async def main():
x = asyncio.gather(
asyncio.to_thread(inc, 0),
asyncio.to_thread(inc, 1)
)
try:
await asyncio.wait_for(x, timeout=5.0)
except asyncio.TimeoutError:
print("timeout!")
asyncio.run(main())
我的期望是该程序将从 0
开始打印数字并在 5 秒后终止。但是,当我执行程序 here 时,我没有看到任何输出和以下警告:
/usr/lib/python3.9/asyncio/events.py:80: RuntimeWarning: coroutine 'inc' was never awaited
self._context.run(self._callback, *self._args)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
/usr/lib/python3.9/concurrent/futures/thread.py:85: RuntimeWarning: coroutine 'inc' was never awaited
del work_item
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
asyncio.to_thread 将 常规 函数转换为协程。
您只需将 async def inc
更改为 def inc
。可以这样做,因为没有await
,不是真正的协程
但是,您不能终止线程。超时会导致停止等待,而不是停止计算数字。
更新:详细来说,asyncio.gather
等待协程直到超时。当超时取消时,gather
取消所有仍然 运行 协程 a 并等待它们终止。取消协程意味着在最近的 await
语句处传递异常。在这种情况下,没有 await
并且协程永远不会收到取消异常。程序在那一点挂起。