TL; DR: не используйте блокирующие вызовы, такие как time.sleep
, в сопрограмме. Используйте asyncio.sleep
для асинхронной паузы или событие l oop исполнитель , если блокирующий код должен быть запущен.
Использование asyncio.wait([thing])
добавляет уровень косвенности, выполнение 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)
, он отключает событие l oop и все другие сопрограммы.
async def coro2():
logger.info("coro2 start")
time.sleep(10) # nothing happens for 10 seconds
logger.info("coro2 finish")
Это предотвращает запуск дальнейших Futures, включая новое будущее от asyncio.wait
, и от возобновления, включая голый asyncio.sleep(5)
. В первом случае это означает, что asyncio.sleep
запускается после , time.sleep
завершается, поэтому для завершения требуется 10 + 5
секунд. В последнем случае это означает, что asyncio.sleep
уже запущен, он просто не может завершить до 10 секунд, поэтому для завершения требуется max(10, 5)
секунд.
Последовательно используйте asyncio.sleep
, чтобы получить желаемую продолжительность. Если блокирующий код должен быть выполнен, пусть он запускается через исполнитель .
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())