zoukankan      html  css  js  c++  java
  • Python上下文管理器

    Python上下文管理器

    简介

    最近用到这个,仔细了解了一下,感觉是十分有用的,记录一下

    使用场景

    当我们需要获取一个临时打开的资源,并在使用完毕后进行资源释放和异常处理,利用try-catch语句可以完成,举个例子。
    打开文件:

    f = None
    try:
        print("try")
        f = open("__init__.py", "r")
        print(f.read())
    except Exception as e:
        print("exception")
    finally:
        if f:
            print("finally")
            f.close()
    

    利用上下文管理器:

    class OpenHandle:
    
        def __init__(self, filename, mode):
            self.filename = filename
            self.mode = mode
    
        def __enter__(self):
            self.f = open(self.filename, self.mode)
            return self.f
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            if exc_type:
                print("exception")
            else:
                print("normal")
            self.f.close()
    
    with OpenHandle("book.txt", "r") as f:
        print(f.read())
    

    这样可以利用with-as语句改写代码,让程序员关注业务主流程,去掉对于资源的获取和关闭这些重复操作。提升代码的可读性。好处很大。

    执行顺序

    执行顺序是理解这种写法的关键:

    1. 初始化,执行handle的__init__()
    2. __enter__()方法,获取资源对象,返回给as后的变量
    3. 业务代码逻辑
    4. __exit__方法,传入3个参数,异常类型,异常对象,调用栈对象,无异常都为None
    5. 抛出异常或者正常结束

    函数式上下文管理器

    利用from contextlib import contextmanager这个装饰器可以将函数装饰为上下文管理器,其实这个装饰背后也是返回一个实现了__enter__和__exit__方法的类

    from contextlib import contextmanager
    
    @contextmanager
    def managed_resource(*args, **kwds):
        # Code to acquire resource, e.g.:
        resource = acquire_resource(*args, **kwds)
        try:
            yield resource
        finally:
            # Code to release resource, e.g.:
            release_resource(resource)
    
    >>> with managed_resource(timeout=3600) as resource:
    ...     # Resource is released at the end of this block,
    ...     # even if code in the block raises an exception
    

    模板代码

    sqlalchemy会话上下文管理器

    利用这个管理sqlalchemy会话对象的获取和释放,控制事务是再合适不过了

    class DbTransaction:
    
        def __init__(self, session_maker):
            self.session_maker = session_maker
    
        def __enter__(self):
            self.session = self.session_maker()
            # self.session.begin()   #如果session_make()是auto_commit=True就要写
            return self.session
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            if exc_type:
                self.session.rollback()
            else:
                self.session.commit()
            self.session.close()
            return False if exc_type else True
    
  • 相关阅读:
    grafana邮箱配置
    grafana集群配置
    CentOS7 配置OOM监控报警
    Mycat使用配置实践
    CentOS7安装JAVA环境
    CentOS7安装MYCAT中间件
    CentOS7安装MySQL5.6
    Mockingbird
    堆的建立与功能实现
    Matlab解决线性规划问题
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/11842570.html
Copyright © 2011-2022 走看看