在python asyncio中是否有理由`return await ...`?

Uri*_*Uri 10 python return async-await python-asyncio

我知道在 js 中它没有awaitreturn语句之前添加任何内容(即return await ...),但是在 python 中也是如此,或者这以某种方式使物化更有可能或不同?

如果两者不等价,最佳实践是什么?

dec*_*eze 16

鉴于:

async def foo() -> str:
    return 'bar'
Run Code Online (Sandbox Code Playgroud)

调用时您得到的fooAwaitable,这显然是您想要的await。您需要考虑的是函数的返回值。例如,您可以这样做:

def bar() -> Awaitable[str]:
    return foo()  # foo as defined above
Run Code Online (Sandbox Code Playgroud)

那里有bar一个同步函数,但返回一个Awaitable结果为str.

async def bar() -> str:
    return await foo()
Run Code Online (Sandbox Code Playgroud)

上面,bar本身 isasync和导致Awaitable调用 when 导致 a str,与上面相同。这两种用法之间没有真正的区别。差异出现在这里:

async def bar() -> Awaitable[str]:
    return foo()
Run Code Online (Sandbox Code Playgroud)

在那个例子中,调用bar结果Awaitable是 a Awaitable,结果是 a str;很不一样。如果你天真地使用上面的,你会得到这样的结果:

>>> asyncio.run(bar())
<coroutine object foo at 0x108706290>
RuntimeWarning: coroutine 'foo' was never awaited
Run Code Online (Sandbox Code Playgroud)

根据经验,每次调用 an 都async必须在await某处编辑一次。如果您有两个async( async def fooand async def bar) 但没有awaitin bar,则调用者bar必须await两次,这很奇怪。

  • Python 的口头禅是“显式优于隐式”,因此每个“async”一个“await”非常有意义,让您可以完全控制。 (5认同)

dre*_*-hh 9

TL)@deceze 的 DR 答案。

是的,这是有原因的。return await调用另一个协程时总是来自一个协程。

Async函数总是返回一个 Awaitable,即使是一个普通的return. 您只能通过调用获得实际结果await。没有return await结果是一个额外包装的 Awaitable 并且必须等待两次。见文档。

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())

Run Code Online (Sandbox Code Playgroud)