Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does await guarantee execution order?

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?

like image 516
Terris Avatar asked Sep 19 '25 00:09

Terris


1 Answers

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
like image 91
Mikhail Gerasimov Avatar answered Sep 23 '25 11:09

Mikhail Gerasimov