python - `asyncio.wait([asyncio.sleep(5)])` 和 `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
异步暂停,如果必须运行阻塞代码,则使用事件循环执行器。
Usingasyncio.wait([thing])
增加了一个间接级别,thing
在一个新的 Future/Task 中执行。当 bareawait asyncio.sleep(5)
在 期间执行 sleep 时coro1
, Wrapped在所有其他当前调度的协程之后await asyncio.wait([asyncio.sleep(5)])
执行 sleep 。
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
- 和被恢复 - 包括 bare asyncio.sleep(5)
。在前一种情况下,这意味着完成asyncio.sleep
后开始time.sleep
- 因此需要10 + 5
几秒钟才能完成。在后一种情况下,这意味着asyncio.sleep
已经开始,它只是无法在 10 秒之前完成- 因此需要max(10, 5)
几秒钟才能完成。
始终使用asyncio.sleep
以获得所需的持续时间。如果必须执行阻塞代码,让它通过 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())
推荐阅读
- c# - C# Grpc 服务器的 Angular 6 客户端 - 在 nodeHttp.js 中出现错误
- mysql - 如何从所有组中获取最高总数的 id?(MySQL)
- c++ - 将对象指针设置为 0(空)时出现“未定义对 vtable 的引用”错误,如果未定义则没有错误
- java - 无法将对象放入地图
- c# - Admob 横幅广告在 Unity3D 中无法正常工作
- typescript - 带有打字稿的原子 - 见参数列表
- kivy - 如何不变地显示kivy按钮的背景图像?
- angular - Angular 复杂组件通信
- javascript - 使用 hAxis 刻度时,Google 组合图表不显示带有阶梯区域的烛台
- python - python 3.4.4中的langdetect库导入错误