zoukankan      html  css  js  c++  java
  • 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
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    【20210930】连岳摘抄
    【20211002】连岳摘抄
    网站首页head区代码规范(网页设计师必看)
    让你的VMware Workstation随主系统自动启动
    asp中使用图片验证码的方法
    文本筐怎样让它只能输入数字(以及怎么只能输入一个小数点和数字)
    asp通用分页函数
    系统安装秘技:精心打造WinXP万能GHOST(图)
    asp调用存储过程
    在 win2k3 下安装 webeasymail
  • 原文地址:https://www.cnblogs.com/shenjianping/p/14864769.html
Copyright © 2011-2022 走看看