8

In Python, we need an await keyword before each coroutine object to have it called by the event loop. But when we put await, it makes the call blocking. It follows that we end up doing the same thing as we do in the blocking fashion. What is the point of having such a use?

https://www.aeracode.org/2018/02/19/python-async-simplified/

https://stackabuse.com/python-async-await-tutorial/

ibrahim koz
  • 537
  • 4
  • 15
  • Does this answer your question? [How does asyncio actually work?](https://stackoverflow.com/questions/49005651/how-does-asyncio-actually-work) – MisterMiyagi Sep 09 '21 at 12:43
  • 2
    "But when we put ``await``, it makes the call blocking." What makes you think that? The first links says for example "Coroutines run synchronously until they hit an await and **then they pause, give up control to the event loop, and something else can happen.**" – MisterMiyagi Sep 09 '21 at 12:44
  • The following lines after the line in which `await` is called have to wait for the promise to resolve. So it is blocking its scope, am I wrong? So unlike JS, which we don't have to put await, we need to block the scope for each async function. This reduces the same thing. I'm so confused. – ibrahim koz Sep 09 '21 at 12:56
  • 1
    The point of ``await`` is that *other* coroutines ("scopes") can run while the current one is suspended ("blocks"). – MisterMiyagi Sep 09 '21 at 13:01
  • Does this answer your question? [How does asyncio actually work?](https://stackoverflow.com/questions/49005651/how-does-asyncio-actually-work) – ggorlen Sep 09 '21 at 18:12

2 Answers2

10

Using await does NOT make the call synchronous. It is just syntactic sugar to make it look like "normal" sequential code. But while the result of the function call is awaited the event loop still continues in the background.

For example the following code executes foo() twice which will await a sleep. But even though it uses await the second function invokation will execute before the first one finishes. Ie. it runs in parallel.

import asyncio

async def main():
    print('started')
    await asyncio.gather(
        foo(),
        foo(),
    )

async def foo():
    print('starting foo')
    await asyncio.sleep(0.1)
    print('foo finished.')

asyncio.run(main())

prints:

started
starting foo
starting foo
foo finished.
foo finished.
Herbert Poul
  • 4,512
  • 2
  • 31
  • 48
  • 1
    "parallel" is misleading. you mean concurrent – uzumaki May 19 '23 at 15:16
  • I think the author of the question asked about the coroutine being blocked. Yes. The await call blocks. It does not block the entire thread of python. But it definitely blocks the particular coroutine in which await is called. If there is another coroutine then the event loop can execute this one. I think what people expect is that python would make an asynchronous call and when this call is done a callback function is called. We do not have callbacks here. – sajid Jun 20 '23 at 07:06
2

await makes the call locally blocking, but the "wait" is transmitted through the async function (which is itself awaited), such that when it reaches the reactor the entire task can be moved to a waitlist and an other can be run instead.

Furthermore you do not need an await, you could also spawn the coroutine (to a separate task, which you may or may not wait on), or use one of the "future combinators" (asyncio.gather, asyncio.wait, ...) to run it concurrently with others.

Masklinn
  • 34,759
  • 3
  • 38
  • 57