`asyncio.wait([asyncio.sleep(5)])` 和 `asyncio.sleep(5)` 之间的区别
Difference between `asyncio.wait([asyncio.sleep(5)])` and `asyncio.sleep(5)`
有人可以解释为什么 coro2
完成和 coro1
完成之间有 5 秒的延迟吗?
还有,为什么我把asyncio.wait([asyncio.sleep(5)])
换成asyncio.sleep(5)
就没有延迟了?
async def coro1():
logger.info("coro1 start")
await asyncio.wait([asyncio.sleep(5)])
logger.info("coro1 finish")
async def coro2():
logger.info("coro2 start")
time.sleep(10)
logger.info("coro2 finish")
async def main():
await asyncio.gather(coro1(), coro2())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
2020-05-25 12:44:56 coro1 start
2020-05-25 12:44:56 coro2 start
2020-05-25 12:45:06 coro2 finish
2020-05-25 12:45:11 coro1 finish
TLDR:不要在协程中使用阻塞调用,例如 time.sleep
。使用 asyncio.sleep
异步暂停,或者如果阻塞代码必须是 运行.
,则使用 an event loop executor
使用 asyncio.wait([thing])
添加一个间接级别,在新的 Future/Task 中执行 thing
。裸机 await asyncio.sleep(5)
在 coro1
期间执行睡眠,而包装 await asyncio.wait([asyncio.sleep(5)])
在所有 其他当前调度的协程之后执行睡眠 。
async def coro1():
logger.info("coro1 start")
await asyncio.sleep(5) # started immediately
logger.info("coro1 finish")
async def coro1():
logger.info("coro1 start")
await asyncio.wait([ # started immediately
asyncio.sleep(5) # started in new task
])
logger.info("coro1 finish")
由于 coro2
使用阻塞 time.sleep(10)
,它禁用了事件循环和所有其他协程。
async def coro2():
logger.info("coro2 start")
time.sleep(10) # nothing happens for 10 seconds
logger.info("coro2 finish")
这会阻止进一步的 Futures 被启动 - 包括来自 asyncio.wait
的新 future - 以及被恢复 - 包括裸 asyncio.sleep(5)
。在前一种情况下,这意味着 asyncio.sleep
在 之后开始 time.sleep
完成 - 因此需要 10 + 5
秒才能完成。在后一种情况下,这意味着 asyncio.sleep
已经开始,它无法在 10 秒结束之前 完成 - 因此需要 max(10, 5)
秒才能完成。
始终使用 asyncio.sleep
以获得所需的持续时间。如果必须执行阻塞代码,让它 run via an executor.
async def coro1w():
print("coro1w start", time.asctime())
await asyncio.wait([asyncio.sleep(5)])
print("coro1w finish", time.asctime())
async def coro1b():
print("coro1b start", time.asctime())
await asyncio.sleep(5)
print("coro1b finish", time.asctime())
async def coro2a():
print("coro2a start", time.asctime())
await asyncio.sleep(10) # asynchronous sleep
print("coro2a finish", time.asctime())
async def coro2t():
print("coro2t start", time.asctime())
loop = asyncio.get_running_loop() # threaded sleep
await loop.run_in_executor(None, lambda: time.sleep(10))
print("coro2t finish", time.asctime())
async def main():
await asyncio.gather(coro1w(), coro1b(), coro2a(), coro2t())
asyncio.run(main())
有人可以解释为什么 coro2
完成和 coro1
完成之间有 5 秒的延迟吗?
还有,为什么我把asyncio.wait([asyncio.sleep(5)])
换成asyncio.sleep(5)
就没有延迟了?
async def coro1():
logger.info("coro1 start")
await asyncio.wait([asyncio.sleep(5)])
logger.info("coro1 finish")
async def coro2():
logger.info("coro2 start")
time.sleep(10)
logger.info("coro2 finish")
async def main():
await asyncio.gather(coro1(), coro2())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
2020-05-25 12:44:56 coro1 start
2020-05-25 12:44:56 coro2 start
2020-05-25 12:45:06 coro2 finish
2020-05-25 12:45:11 coro1 finish
TLDR:不要在协程中使用阻塞调用,例如 time.sleep
。使用 asyncio.sleep
异步暂停,或者如果阻塞代码必须是 运行.
使用 asyncio.wait([thing])
添加一个间接级别,在新的 Future/Task 中执行 thing
。裸机 await asyncio.sleep(5)
在 coro1
期间执行睡眠,而包装 await asyncio.wait([asyncio.sleep(5)])
在所有 其他当前调度的协程之后执行睡眠 。
async def coro1():
logger.info("coro1 start")
await asyncio.sleep(5) # started immediately
logger.info("coro1 finish")
async def coro1():
logger.info("coro1 start")
await asyncio.wait([ # started immediately
asyncio.sleep(5) # started in new task
])
logger.info("coro1 finish")
由于 coro2
使用阻塞 time.sleep(10)
,它禁用了事件循环和所有其他协程。
async def coro2():
logger.info("coro2 start")
time.sleep(10) # nothing happens for 10 seconds
logger.info("coro2 finish")
这会阻止进一步的 Futures 被启动 - 包括来自 asyncio.wait
的新 future - 以及被恢复 - 包括裸 asyncio.sleep(5)
。在前一种情况下,这意味着 asyncio.sleep
在 之后开始 time.sleep
完成 - 因此需要 10 + 5
秒才能完成。在后一种情况下,这意味着 asyncio.sleep
已经开始,它无法在 10 秒结束之前 完成 - 因此需要 max(10, 5)
秒才能完成。
始终使用 asyncio.sleep
以获得所需的持续时间。如果必须执行阻塞代码,让它 run via an executor.
async def coro1w():
print("coro1w start", time.asctime())
await asyncio.wait([asyncio.sleep(5)])
print("coro1w finish", time.asctime())
async def coro1b():
print("coro1b start", time.asctime())
await asyncio.sleep(5)
print("coro1b finish", time.asctime())
async def coro2a():
print("coro2a start", time.asctime())
await asyncio.sleep(10) # asynchronous sleep
print("coro2a finish", time.asctime())
async def coro2t():
print("coro2t start", time.asctime())
loop = asyncio.get_running_loop() # threaded sleep
await loop.run_in_executor(None, lambda: time.sleep(10))
print("coro2t finish", time.asctime())
async def main():
await asyncio.gather(coro1w(), coro1b(), coro2a(), coro2t())
asyncio.run(main())