Reputation: 171
async def caller():
await bar()
print("finish")
async def bar():
// some code here
async def caller():
bar()
print("finish")
def bar():
//some code here
In above example. caller has to wait for the completion of bar() for both cases. Any difference for bar to be a normal / coroutine for this situation? If we want to "await" some functions, why not just use a normal function.
Upvotes: 13
Views: 9851
Reputation: 635
A coroutine can't run in the simply calling, it need to run in event loop. The event loop will listen for the events that we add into the event pool and execute callback when the event fire And when it execute the "await" part of the code, it probably means that there are some I/O bounds task, so that the event loop will go on next event, so that won't block the thread.
Upvotes: 0
Reputation: 155630
The difference is that in the second example bar()
is a non-async function, so it itself cannot await anything. For example, if you wanted to access a web service from within bar()
, it wouldn't be a problem in the first example, you'd just use aiohttp. In the second example it would be pretty much impossible, as async libraries require being used from async functions, and non-async libraries will block the whole event loop while waiting for response.
If we want to "await" some functions, why not just use a normal function.
If the function you await doesn't need to communicate with the outside world (e.g. if it just shuffles data in a dict or so), it can and should be a normal function. On the other hand, if it needs to do IO, it should be an async function.
Upvotes: 7
Reputation: 522626
If it's not an async
function, then you don't need to await
it obviously. Not every function you call inside an async
function must be async
nor must be await
ed; you can call regular non-async functions from within an async
function.
The entire asyncio model works around an event loop. Only one task can run at any one time, and the event loop coordinates what is currently running. An await
inside a function suspends the execution of that function and allows another task to be run on the event loop. So, in this example:
async def caller():
await bar()
print('finish')
The execution goes like this:
caller()
is called and scheduled on the event loop, which will execute it as soon as an availability exists.bar()
, which schedules its execution on the event loop.await
suspends the execution of caller
.bar
; let's say it's making a network request, so nothing will happen until that response returns, the event loop is free to run any other scheduled async tasks…bar
.bar
ends, the event loop resumes the execution of caller
.await
exists to coordinate the sequence in which asynchronous tasks are run and what task depends on the result of what other task.
Upvotes: 2