From f0866bc2050552621566ca0c0fd111936ac36918 Mon Sep 17 00:00:00 2001 From: xuvjso Date: Tue, 20 Aug 2024 01:35:03 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20Update=20docs=20about=20dependen?= =?UTF-8?q?cies=20with=20yield=20(#12028)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dependencies/dependencies-with-yield.md | 269 +++++++++++++----- 1 file changed, 197 insertions(+), 72 deletions(-) diff --git a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md index beca95d45..6058f7878 100644 --- a/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh/docs/tutorial/dependencies/dependencies-with-yield.md @@ -1,12 +1,12 @@ # 使用yield的依赖项 -FastAPI支持在完成后执行一些额外步骤的依赖项. +FastAPI支持在完成后执行一些额外步骤的依赖项. -为此,请使用 `yield` 而不是 `return`,然后再编写额外的步骤(代码)。 +为此,你需要使用 `yield` 而不是 `return`,然后再编写这些额外的步骤(代码)。 -/// tip | "提示" +/// tip | 提示 -确保只使用一次 `yield` 。 +确保在每个依赖中只使用一次 `yield`。 /// @@ -25,7 +25,7 @@ FastAPI支持在完成后执行一些> tasks: Send background tasks end opt Raise other exception - tasks -->> dep: Raise other exception - end - Note over dep: After yield - opt Handle other exception - dep -->> dep: Handle exception, can't change response. E.g. close DB session. + tasks -->> tasks: Handle exceptions in the background task code end ``` -/// info +/// info | 说明 -只会向客户端发送**一次响应**,可能是一个错误响应之一,也可能是来自*路径操作*的响应。 +只会向客户端发送 **一次响应** ,可能是一个错误响应,也可能是来自 *路由函数* 的响应。 在发送了其中一个响应之后,就无法再发送其他响应了。 /// -/// tip +/// tip | 提示 + +这个时序图展示了 `HTTPException`,除此之外你也可以抛出任何你在使用 `yield` 的依赖项中或者[自定义异常处理器](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}中捕获的异常。 + +如果你引发任何异常,它将传递给使用 `yield` 的依赖项,包括 `HTTPException`。在大多数情况下你应当从使用 `yield` 的依赖项中重新抛出捕获的异常或者一个新的异常来确保它会被正确的处理。 + +/// + +## 包含 `yield`, `HTTPException`, `except` 的依赖项和后台任务 + +/// warning | 注意 + +你大概率不需要了解这些技术细节,可以跳过这一章节继续阅读后续的内容。 + +如果你使用的FastAPI的版本早于0.106.0,并且在使用后台任务中使用了包含 `yield` 的依赖项中的资源,那么这些细节会对你有一些用处。 + +/// + +### 包含 `yield` 和 `except` 的依赖项的技术细节 + +在FastAPI 0.110.0版本之前,如果使用了一个包含 `yield` 的依赖项,你在依赖项中使用 `except` 捕获了一个异常,但是你没有再次抛出该异常,这个异常会被自动抛出/转发到异常处理器或者内部服务错误处理器。 + +### 后台任务和使用 `yield` 的依赖项的技术细节 + +在FastAPI 0.106.0版本之前,在 `yield` 后面抛出异常是不可行的,因为 `yield` 之后的退出代码是在响应被发送之后再执行,这个时候异常处理器已经执行过了。 -这个图表展示了`HTTPException`,但你也可以引发任何其他你创建了[自定义异常处理程序](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}的异常。 +这样设计的目的主要是为了允许在后台任务中使用被依赖项`yield`的对象,因为退出代码会在后台任务结束后再执行。 -如果你引发任何异常,它将传递给带有`yield`的依赖,包括`HTTPException`,然后**再次**传递给异常处理程序。如果没有针对该异常的异常处理程序,那么它将被默认的内部`ServerErrorMiddleware`处理,返回500 HTTP状态码,告知客户端服务器发生了错误。 +然而这也意味着在等待响应通过网络传输的同时,非必要的持有一个 `yield` 依赖项中的资源(例如数据库连接),这一行为在FastAPI 0.106.0被改变了。 + +/// tip | 提示 + +除此之外,后台任务通常是一组独立的逻辑,应该被单独处理,并且使用它自己的资源(例如它自己的数据库连接)。 + +这样也会让你的代码更加简洁。 /// +如果你之前依赖于这一行为,那么现在你应该在后台任务中创建并使用它自己的资源,不要在内部使用属于 `yield` 依赖项的资源。 + +例如,你应该在后台任务中创建一个新的数据库会话用于查询数据,而不是使用相同的会话。你应该将对象的ID作为参数传递给后台任务函数,然后在该函数中重新获取该对象,而不是直接将数据库对象作为参数。 + ## 上下文管理器 -### 什么是“上下文管理器” +### 什么是"上下文管理器" -“上下文管理器”是您可以在`with`语句中使用的任何Python对象。 +"上下文管理器"是你可以在 `with` 语句中使用的任何Python对象。 -例如,您可以使用`with`读取文件: +例如,你可以使用`with`读取文件: ```Python with open("./somefile.txt") as f: @@ -254,38 +379,38 @@ with open("./somefile.txt") as f: print(contents) ``` -在底层,`open("./somefile.txt")`创建了一个被称为“上下文管理器”的对象。 +在底层,`open("./somefile.txt")`创建了一个被称为"上下文管理器"的对象。 -当`with`块结束时,它会确保关闭文件,即使发生了异常也是如此。 +当 `with` 代码块结束时,它会确保关闭文件,即使发生了异常也是如此。 -当你使用`yield`创建一个依赖项时,**FastAPI**会在内部将其转换为上下文管理器,并与其他相关工具结合使用。 +当你使用 `yield` 创建一个依赖项时,**FastAPI** 会在内部将其转换为上下文管理器,并与其他相关工具结合使用。 -### 在依赖项中使用带有`yield`的上下文管理器 +### 在使用 `yield` 的依赖项中使用上下文管理器 -/// warning +/// warning | 注意 -这是一个更为“高级”的想法。 +这是一个更为"高级"的想法。 -如果您刚开始使用**FastAPI**,您可能暂时可以跳过它。 +如果你刚开始使用 **FastAPI** ,你可以暂时可以跳过它。 /// 在Python中,你可以通过创建一个带有`__enter__()`和`__exit__()`方法的类来创建上下文管理器。 -你也可以在**FastAPI**的依赖项中使用带有`yield`的`with`或`async with`语句,通过在依赖函数内部使用它们。 +你也可以在 **FastAPI** 的 `yield` 依赖项中通过 `with` 或者 `async with` 语句来使用它们: ```Python hl_lines="1-9 13" {!../../../docs_src/dependencies/tutorial010.py!} ``` -/// tip +/// tip | 提示 另一种创建上下文管理器的方法是: * `@contextlib.contextmanager`或者 * `@contextlib.asynccontextmanager` -使用上下文管理器装饰一个只有单个`yield`的函数。这就是**FastAPI**在内部用于带有`yield`的依赖项的方式。 +使用它们装饰一个只有单个 `yield` 的函数。这就是 **FastAPI** 内部对于 `yield` 依赖项的处理方式。 但是你不需要为FastAPI的依赖项使用这些装饰器(而且也不应该)。FastAPI会在内部为你处理这些。