FastAPI依赖注入系统系列(六) 带有yield功能的依赖项

一、yield在依赖项中的使用

 FastAPI支持依赖项在完成请求后做一些额外的工作。为了做到这些使用yield而不是用return,并且写一些额外的步骤。

使用yield功能需要使用python3.7或者之上的版本支持,如果在python3.6需要安装以下的工具:

pip install async-exit-stack async-generator

 对于yield的使用:

async def get_db():
    db = DBSession()
    try:
        yield db
    finally:
        db.close()

你可以使用yield去创建一个数据库连接,并且在完成这个过程后去关闭它。

  • 在发送响应之前只执行yield之前的代码
  • yield产生的值会注入到路径操作或者其它依赖项
  • yield后面的代码会在响应后执行

另外你也可以在子依赖项中来进行使用:

from fastapi import Depends


async def dependency_a():
    dep_a = generate_dep_a()
    try:
        yield dep_a
    finally:
        dep_a.close()


async def dependency_b(dep_a=Depends(dependency_a)):
    dep_b = generate_dep_b()
    try:
        yield dep_b
    finally:
        dep_b.close(dep_a)


async def dependency_c(dep_b=Depends(dependency_b)):
    dep_c = generate_dep_c()
    try:
        yield dep_c
    finally:
        dep_c.close(dep_b)

  上面所有的依赖项都可以使用yield来实现,在这个例子中,当dependency_c执行它的退出代码,仍然需要保证dependency_b仍然是可用的。同理dependency_b执行退出代码dependency_a的值也是可用的。

  同样的,你可以使用yield与return进行混合使用,或者创建一个依赖项和几个其它yield的子依赖项。总之,可以进行依赖项之间的任意组合,FastAPI会确保这些依赖项按照正确的顺序执行。

  不过执行过程中难免出现异常情况,如果在带有yield的依赖项中使用try块的话,你将会在依赖项中接收到随时抛出的异常。所以你可以使用finally来确保不管是否有异常,都执行退出的代码。

async def get_db():
    db = DBSession()
    try:
        yield db
    finally:
        db.close()

  注意的是,如果在yield之后抛出一些异常,如HTTPException等,这是行不通的,因为异常处理是是yield之前进行的,如果在yield之后抛出异常,没有任何处理机制去捕获这些异常。

二、上下文管理器

上下文管理器是任何你可以在with语句中使用的python对象。

比如,可以使用with来读一个文件:

with open("./example.txt") as f:
    contents = f.read()

  通过open("./example.txt")创建一个上下问管理器的对象,当这个with块完成后,即使执行发生异常,它也能确保关闭这个文件。在FastAPI中,当你创建一个带yield功能的依赖项,其内部就是将它转成一个上下文管理器

 在Python中你可以通过__enter__()和__exit__()两个方法创建一个上下文管理器。然后将它应用到FastAPI中带yield功能的依赖项中。

class MySuperContextManager:
    def __init__(self):
        self.db = DBSession()

    def __enter__(self):
        return self.db

    def __exit__(self, exc_type, exc_value, traceback):
        self.db.close()


async def get_db():
    with MySuperContextManager() as db:
        yield db
作者:iveBoy
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/shenjianping/p/14864769.html