• 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
    
  • 相关阅读:
    LeetCode Flatten Binary Tree to Linked List
    LeetCode Longest Common Prefix
    LeetCode Trapping Rain Water
    LeetCode Add Binary
    LeetCode Subsets
    LeetCode Palindrome Number
    LeetCode Count and Say
    LeetCode Valid Parentheses
    LeetCode Length of Last Word
    LeetCode Minimum Depth of Binary Tree
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/11842570.html
Copyright © 2020-2023  润新知