python上下文管理器小记

1.实现了上下文协议的对象可以使用with关键字
2.实现了上下文协议的对象通常称为上下文管理器
3.只要对象实现了__enter__和__exit__就是实现了上下文协议
4.上下文表达式必须要返回一个上下文管理器(with xxx():就是上下文表达式)

class MyResource:
    def __enter__(self):
        print("connect to resource")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        :param exc_type: 错误类型
        :param exc_val: 错误信息
        :param exc_tb: traceback对象
        :return:
        """
        if exc_tb:
            # 可以在这里处理异常
            print("process exception")
        else:
            print("no exception")

        print("close resource connection")

        # __exit__方法必须要返回一个True或者False,如果什么都不返回,就会返回False
        # 当with中发生了异常,若返回True则在with语句外部则不会在抛出异常;若是False则会再次抛出异常
        return True

    def query(self):
        print("query data")


with MyResource() as resource:
    # as 后面的变量是__enter__中返回的值
    resource.query()

# 执行顺序 __enter__ -> query -> __exit__

使用contextmanager来简化MyResource定义

from contextlib import contextmanager
# contextmanager好处是将不是上下管理器的类变成了一个管理器


class MyResource:
    def query(self):
        print("query data")


@contextmanager
def make_my_resource():
    # __enter__
    print("connect to resource")
    yield MyResource()

    # __exit__
    print("close resource connection")


with make_my_resource() as resource:
    resource.query()

eg1:实现给一个字符串前后加上书名号

from contextlib import contextmanager


@contextmanager
def book_mark():
    print("《", end="")
    yield
    print("》", end="")


with book_mark():
    print("唐诗三百首", end="")

# output: 《唐诗三百首》

eg2:给SQLAlchemy添加一个auto_commit

from contextlib import contextmanager

from flask_sqlalchemy import SQLAlchemy as _SQLAlchemy


class SQLAlchemy(_SQLAlchemy):
    @contextmanager
    def auto_commit(self):
        try:
            yield
            self.session.commit()
        except Exception as e:
            db.session.rollback()
            raise e


db = SQLAlchemy()

with db.auto_commit():
    user = User()

    user.name = "xiaoming"
    user.password = "hello"

    db.session.add(user)
Last modification:April 12th, 2019 at 12:04 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment