python:Fastapi - 依赖项中使用上下文管理器

python:Fastapi - 依赖项中使用上下文管理器,第1张

什么是上下文管理器

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

例如:您可以使用with关键字读取文件

with open("./file.txt") as f:
    data= f.read()
    print(data)

运行时,open("./file.txt")会创建一个称为上下文管理器的对象。

with块完成时,它确保关闭文件,即使有异常。

如自定义上下文管理器,那类中必须要有下面两个魔术方法

    def __enter__(self):
        pass

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        :param exc_type: 异常类型
        :param exc_val: 值
        :param exc_tb: 回溯信息
        :return:
        """
        pass

object.__enter__(self):输入与此对象相关的运行时上下文。with语句会将此方法的返回值绑定到该as语句子句中指定的目标变量上。

object.__exit__(self, exc_type, exc_val, exc_tb):退出与此对象相关的运行时上下文。如果上下文无异常退出,则所有三个参数都是None。如果在执行语句主体时发生异常,则参数包含异常类型、值和回溯信息。

在前面我们的项目中,有数据库的 *** 作,我们当初的写法是这样的:

def get_db():
    db = _DBConnect.SessionLocal()
    try:
        yield db
    finally:
        db.close()

先实例化,然后开始捕获异常,如果没有异常则执行finally,如果有异常也执行finally,这个关键字就是个流氓,甭管你想要或是不想要,我都要上

那现在我们改成上下文管理器来运行数据库的 *** 作,修改如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/4/21 19:07
# @Author  : Lifeng
# @File    : databases.py
# @Software: PyCharm

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

__all__ = [
    "BASE",
    "get_db"
]


class _DBConnect:
    # 定义一个变量
    _SQLALCHEMY_DATABASE_URL = "sqlite:///./sc_database.db"

    # 创建一个连接
    _engine = create_engine(
        _SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
    )

    # 创建一个持久对象,好处就是可以一次添加多个对象
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=_engine)

    # 定义一个ORM模型基类
    Base = declarative_base()
    # 绑定连接,使用表元数据和引擎
    Base.metadata.create_all(bind=_engine)


class _ConnectDB:
    def __init__(self):
        self._db = _DBConnect.SessionLocal()

    def __enter__(self):
        return self._db

    def __exit__(self, exc_type, exc_val, exc_tb):
        self._db.close()


def get_db():
    """
    初始化持久对象,并yield返回
    无论失败与否最后都会调用关闭
    :return:
    """
    with _ConnectDB() as db:
        yield db


# _DBConnect.Base赋值给BASE变量
BASE = _DBConnect.Base

只修修改了内部代码,其余的无需变动,当然你也可以不作任何修改,继续使用try...finally的。

上下文管理器这只是一种方法,可以使用装饰器函数@contextlib.contextmanager@contextlib.asynccontextmanager,可自行了解下。


今天先聊到这里吧,以上总结或许能帮助到你,或许帮助不到你,但还是希望能帮助到你,如有疑问、歧义,直接私信留言会及时修正发布;非常期待你的一键 3 连【 点赞、收藏、分享 】哟,谢谢!

未完成,待续……

一直在努力,希望你也是!

微信搜索公众号:就用python

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/langs/917844.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-16
下一篇2022-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存