了解异步等待行为

时间:2020-03-03 17:40:57

标签: python-asyncio

我有以下示例代码:

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

为什么会发生这种情况以及我如何才能达到期望的结果?

1 个答案:

答案 0 :(得分:1)

等待协程(例如h())的全部目的是等待以使其完成,并且(在有意义的地方)访问其返回值。例如,line = await stream.readline()暂停当前协程直到readline()完成,然后将结果提供给line

如果您希望h()在后​​台运行,则可以改用asyncio.create_task。但是它仍然不会产生所需的输出,因为run_until_complete(main())仅等待main()完成,而忽略了它可能产生的其他任务。 (它还返回协程的返回值,非常类似于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())