Python进阶-上下文管理器

发布时间 2023-06-20 12:28:21作者: 韩志超

上下文管理器

定义

  • 包装任意代码
  • 确保执行的一致性

语法

  • with语句
  • __enter__和__exit__方法
class ContextManager(object):
    def __init__(self):
        self.entered = False
        
    def __enter__(self):
        self.entered = True
        return self
        
    def __exit__(self, exc_type, exc_instance, traceback):
        self.entered = False

应用场景

资源清理

import pymysql

class DBConnection(object):
    def __init__(self, *args, **kwargs):
        self.args,self.kwargs = args, kwargs
        
    def __enter__(self):
        self.conn = pymysql.connect(*args, **kwargs)
        return self.conn.cursor()
        
    def __exit__(self, exc_type, exc_instance, trackback):
        self.conn.close()

异常处理(避免重复)

  • 传播异常(__exit__中return False)
  • 终止异常(__exit__中return True)
class BubleExceptions(object):
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_instance, trackback):
        if exc_instance:
            print("出现异常: {}".format(exc_instance)
        return False   # return True终止异常
  • 处理特定的异常
class HandleValueError(object):
    def __enter__(self):
        return self
    def __exit__(self, exc_type, exc_instance, trackback):
        if not exc_type: return True
        if issubclass(exc_type, ValueError): 
            print("处理ValueError: {}".format(exc_instance)
        return False

if issubclass...语句改为if exec_type == ValueError则不处理ValueType的子类异常

也可以根据异常的属性来判断是否传播或终止

更简单的语法

import contextlib

@contextlib.contextmanager
def acceptable_error_codes(*codes):
    try:
        yield
    except ShellException as exc_instance:
        if exc_instance.code not in codes:
            raise
        pass