I may break the code up for readability reasons. So
async coro_top():
print('top')
print('1')
# ... More asyncio code
print('2')
# ... More asyncio code
... into something like
async coro_top():
print('top')
await coro_1()
await coro_2()
async coro_1()
print('1')
# ... More asyncio code
async coro_2()
print('2')
# ... More asyncio code
However, the extra await
s mean that these are not strictly equivalent
Another concurrent task can run code between print('top')
and print('1')
, so makes race conditions a touch more likely for certain algorithms.
There is (presumably) a slight overhead in yielding the event loop
So is there a way of calling a coroutine without yielding the event loop in order to avoid the above?
The premise of the question is incorrect: contrary to what people tend to expect, an await
doesn't automatically yield to the event loop. You can easily test that:
async def noop():
pass
async def busy_loop(msg):
while True:
print(msg)
await noop()
# keeps printing 'a', the event loop is stuck
asyncio.get_event_loop().run_until_complete(
asyncio.gather(busy_loop('a'), busy_loop('b')))
Although busy_loop
awaits the whole time, it still blocks the event loop, so that other tasks will not run, and even cancelling it is impossible. This is because the noop
coroutine it awaits never suspends execution.
await some_coroutine()
doesn't mean "schedule some_coroutine()
and yield to the event loop, resuming when it completes". It means "start executing some_coroutine()
and, if/when it chooses to suspend, suspend along", and assuming the former can lead to bugs.
In other words, the broken-up code really is equivalent to the code before the refactoring. The only way for another task to execute between print('top')
and print('1')
is for a new await
to be added between them (one that actually suspends the coroutine), but the same can be said of the original code as well.
There is (presumably) a slight overhead in yielding the event loop
The overhead exists, but it is comparable to the overhead of a function call, not to the significantly larger overhead of running an iteration of the event loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With