为什么我只能在async函数中使用await关键字?

2024-04-29 16:00:43 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有这样的代码

async def fetch_text() -> str:
    return "text "

async def show_something():
    something = await fetch_text()
    print(something)

这很好。但我想清理数据

async def fetch_text() -> str:
    return "text "

def fetch_clean_text(text: str) -> str:
    text = await fetch_text()
    return text.strip(text)

async def show_something():
    something = fetch_clean_text()
    print(something)

(我可以清除show_something()中的文本,但假设show_something()可以打印许多内容,并且不知道或不应该知道正确的清理方法。)

这当然是一个SyntaxError: 'await' outside async function。但是如果这个代码可以在await表达式没有放在协同程序函数中的情况下运行,那么它将在一个函数的上下文中执行。为什么不允许这种行为?

我在这个设计中看到了一个pro;在我的后一个例子中,您看不到show_something()的主体正在做一些可能导致其暂停的事情。但是,如果我将fetch_clean_text()设为协程,不仅会使事情复杂化,而且可能还会降低性能。如果有另一个协同程序本身不执行任何I/O,那就没有什么意义了。有更好的办法吗?


Tags: 函数代码textcleanasyncreturndefshow
1条回答
网友
1楼 · 发布于 2024-04-29 16:00:43

I see one pro in this design; in my latter example, you can't see that show_something()'s body is doing something that can result in its suspension.

这正是它这样设计的原因。编写并发代码可能非常棘手,异步作者认为始终显式标记代码中的挂起位置至关重要。

This article详细解释了它(您可以从“GettothePointalready”段落开始)。

But if I were to make fetch_clean_text() a coroutine, not only would it complicate things but would probably also reduce performance.

在处理I/O时,您几乎完全需要协同工作。使用协同工作时,I/O总是比开销花费更多的时间。所以我想可以这么说-不,与您已经处理过的I/O相比,您不会因为使用协程而浪费大量的执行时间。

Is there a better way?

我可以建议的唯一方法是:最大限度地将处理I/O(异步部分)的逻辑从其余代码(同步部分)中分离出来。

from typing import Awaitable

def clean_text(text: str) -> str:
    return text.strip(text)

async def fetch_text() -> Awaitable[str]:
    return "text "

async def fetch_clean_text(text: str) -> Awaitable[str]:
    text = await fetch_text()
    return clean_text(text)

async def show_something():
    something = await fetch_clean_text()
    print(something)

相关问题 更多 >