понимание asyncio ждут поведения - PullRequest
0 голосов
/ 03 марта 2020

У меня есть следующий пример кода:

from datetime import datetime
import asyncio

async def h():
    print("h() has started")
    await asyncio.sleep(5)
    print("h() has ended")

async def main():
    print("{}: start of program".format(datetime.now()))
    await h()
    print("{}: end of program".format(datetime.now()))

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Я бы ожидал (и хотел бы, чтобы вывод кода) был чем-то вроде следующего:

2020-03-03 17:31:25.379742: start of program
h() has started
2020-03-03 17:31:30.384977: end of program
h() has ended

однако У меня есть следующий вывод:

2020-03-03 17:31:25.379742: start of program
h() has started
h() has ended
2020-03-03 17:31:30.384977: end of program

Есть ли конкретная c причина того, почему это происходит, и как я могу go добиться желаемого результата?

1 Ответ

0 голосов
/ 03 марта 2020

Весь смысл в ожидании сопрограммы, такой как h(), заключается в ожидании его завершения и (где это имеет смысл) доступа к его возвращаемому значению. Например, line = await stream.readline() приостанавливает текущую сопрограмму до завершения readline(), а затем предоставляет результат для присвоения line.

Если вы хотите, чтобы h() работал в фоновом режиме, вы можете использовать asyncio.create_task вместо. Но это все равно не приведет к желаемому результату, потому что run_until_complete(main()) ожидает только от main() до конца sh, игнорируя дополнительные задачи, которые он мог породить. (Он также возвращает возвращаемое значение сопрограммы, очень похоже на syn c, эквивалентный await.)

Если вы хотите дождаться дополнительных задач, вы должны быть явными об этом. Возможно что-то вроде:

async def main():
    bgtasks = []
    print("{}: start of program".format(datetime.now()))
    bgtasks.append(asyncio.create_task(h()))
    print("{}: end of program".format(datetime.now()))
    return bgtasks

async def run_everything():
    more_tasks = await main()
    await asyncio.gather(*more_tasks)

if __name__ == '__main__':
    asyncio.run(run_everything())
...