python - `asyncio.wait([asyncio.sleep(5)])` 和 `asyncio.sleep(5)` 之间的区别

标签 python python-3.x python-asyncio coroutine

有人可以解释一下为什么 coro2 完成和 coro1 完成之间有 5 秒的延迟吗?

另外,如果我用 asyncio.sleep(5) 替换 asyncio.wait([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])添加一个间接级别,执行 thing在一个新的 future /任务中。而裸露await asyncio.sleep(5)coro1期间执行 sleep ,包裹的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")

这会阻止进一步启动 future - 包括来自 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())

关于python - `asyncio.wait([asyncio.sleep(5)])` 和 `asyncio.sleep(5)` 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62001898/

相关文章:

python - 将代码同步到异步,无需重写函数

python - 如何在 Tkinter/TTK 中稍微移动标签中的文本?

python - 如何安全地从 Python 列表中删除元素

python - 如何在 python 中从 LAB (l*a*b) 颜色空间中获取 a channel

python - TypeError : list indices must be integers or slices, not str - 从 json 获取

Python 异步监控

Python 3.5 : slice vs islice vs alternatives? 效率对比

python - 将标准格式日期字符串转换为日期时间对象

json - Python 在读取 JSON 文件时抛出错误

queue - 如何在Python中随机打乱asyncio.Queue?