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.