Does await guarantee execution order?

2019-08-06 19:06发布

Consider a single-threaded Python program. A coroutine named "first" is blocked on I/O. The subsequent instruction is "await second." Is the coroutine "second" guaranteed to execute immediately until it blocks on I/O? Or, can "first" resume executing (due to the I/O operation completing) before "second" is invoked?

1条回答
Rolldiameter
2楼-- · 2019-08-06 20:01

Asyncio implemented a way that second would start executing until it would return control to event loop (it usually happens when it reaches some I/O operation) and only after it first can be resumed. I don't think it somehow guaranteed to you, but hardly believe this implementation will be changed either.

If for some reason you don't want first to resume executing until some part of second reached, it's probably better explicitly to use Lock to block first from executing before moment you want.

Example to show when control returns to event loop and execution flow can be changed:

import asyncio


async def async_print(text):
    print(text)


async def first():
    await async_print('first 1')
    await async_print('first 2')
    await asyncio.sleep(0)  # returning control to event loop
    await async_print('first 3')


async def second():
    await async_print('second 1')
    await async_print('second 2')
    await asyncio.sleep(0)  # returning control to event loop
    await async_print('second 3')


async def main():
    asyncio.ensure_future(first())
    asyncio.ensure_future(second())
    await asyncio.sleep(1)


loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
    loop.run_until_complete(main())
finally:
    loop.run_until_complete(loop.shutdown_asyncgens())
    loop.close() 

Output:

first 1
first 2
second 1
second 2
first 3
second 3
查看更多
登录 后发表回答