I know in js it doesn't add anything to do an await
before a return
statement (i.e. return await ...
), but is it the case in python too, or this somehow makes the materialization more probable or different?
If the two are not equivalent, what is the best practice?
The keyword await passes function control back to the event loop. (It suspends the execution of the surrounding coroutine.) If Python encounters an await f() expression in the scope of g() , this is how await tells the event loop, “Suspend execution of g() until whatever I'm waiting on—the result of f() —is returned.
The main reason to use async/await is to improve a program's throughput by reducing the amount of idle time when performing I/O. Programs with this operator are implicitly using an abstraction called an event loop to juggle multiple execution paths at the same time.
You must use the await keyword if and only if the function you are calling is a coroutine. If async functions are involved there should be an "event loop" which orchestrates these async functions.
return await can also be used in a try/catch statement to catch errors from another function that returns a Promise.
Given:
async def foo() -> str:
return 'bar'
What you get when calling foo
is an Awaitable
, which obviously you'd want to await
. What you need to think about is the return value of your function. You can for example do this:
def bar() -> Awaitable[str]:
return foo() # foo as defined above
There, bar
is a synchronous function but returns an Awaitable
which results in a str
.
async def bar() -> str:
return await foo()
Above, bar
itself is async
and results in an Awaitable
when called which results in a str
, same as above. There's no real difference between these two usages. Differences appear here:
async def bar() -> Awaitable[str]:
return foo()
In that example, calling bar
results in an Awaitable
which results in an Awaitable
which results in a str
; quite different. If you naïvely use the above, you'll get this kind of result:
>>> asyncio.run(bar())
<coroutine object foo at 0x108706290>
RuntimeWarning: coroutine 'foo' was never awaited
As a rule of thumb, every call to an async
must be await
ed somewhere once. If you have two async
(async def foo
and async def bar
) but no await
in bar
, then the caller of bar
must await
twice, which would be odd.
TL)DR of @deceze answer.
Yes, there is a reason. Always return await
from a coroutine when calling another coroutine.
Async
functions always return an Awaitable, even with a plain return
. You only get the actual result by calling await
. Without return await
the result is an extra wrapped Awaitable and must be awaited twice. See doc.
import asyncio
async def nested():
return 42
async def main():
# Nothing happens if we just call "nested()".
# A coroutine object is created but not awaited,
# so it *won't run at all*.
nested()
# Let's do it differently now and await it:
print(await nested()) # will print "42".
asyncio.run(main())
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