千字长文讲解python上下文管理器

1.上下文管理器是一个包装任意代码块的对象。上下文管理器保证进入上下文管理器时,每次执行代码的一致性;当退出上下文管理器时,相关的资源会被正确回收。
2.上下文管理器一定能够保证退出步骤的执行。如果进入上下文管理器,根据定义,一定会有退出步骤。即使内部代码抛出了异常,这点也成立。
3.上下文管理器的功能类似于try、except和finally关键字。通常,这也是一种封装需要被重复使用的try-except-finally结构的有效机制。
4.上下文管理器在Python 2.5中引入。
5.
a.从本质上讲,实际上是with语句对其后代码进行求值(在本例中,就是调用open函数)。该表达式会返回一个对象,该对象包含两个特殊方法:enter__和__exit。__enter__方法返回的结果会被赋给as关键字之后的变量。
b.在本例中,open对应的类就实现了__enter__和__exit__方法。
c.__enter__表示上文方法
d.__exit__表示下文方法,with语句执行完成会自动执行__exit__方法,即使出现异常也会执行该方法
e.__exit__方法带有3个位置参数(不包括self参数):一个异常类型、一个异常实例和一个回溯。如果没有异常,这3个参数全被设置成None,但如果在代码块内有异常发生,则参数被填充了。

with open('/path/to/filename', 'r') as my_file:
    contents = my_file.read()

6.什么是上下文管理器
一个类只要实现了__enter__()和__exit__()这两个方法,通过该类创建的对象我们就称之为上下文管理器。
7.操作文件的上下文管理器的例子
a.正常处理文件

class MyOpen(object):
    def __init__(self, file_name, file_mode):
        self.file_name = file_name
        self.file_mode = file_mode

    def __enter__(self):
        print('这是 __enter__ 函数')
        self.file = open(self.file_name, self.file_mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        :param exc_type:
        :param exc_val:
        :param exc_tb:
        :return:
        """
        print('这是 __exit__ 函数')
        self.file.close()


with MyOpen('1.txt', 'r') as f:
    file_data = f.read()
    print(file_data)

'''
这是 __enter__ 函数
here is some text
这是 __exit__ 函数
'''

b. 处理文件时遇到异常

class MyOpen(object):
   def __init__(self, file_name, file_mode):
       self.file_name = file_name
       self.file_mode = file_mode

   def __enter__(self):
       print('这是 __enter__ 函数')
       self.file = open(self.file_name, self.file_mode)
       return self.file

   def __exit__(self, exc_type, exc_val, exc_tb):
       """
       :param exc_type:
       :param exc_val:
       :param exc_tb:
       :return:
       """
       print('这是 __exit__ 函数')
       self.file.close()


with MyOpen('1.txt', 'r') as f:
   file_data = f.read()
   print(file_data)
   raise Exception('error occur while handling file')
   
'''
这是 __enter__ 函数
here is some text
这是 __exit__ 函数
Traceback (most recent call last):
 File "C:\Users\dyc\PycharmProjects\scripts\with和上下文管理器\上下文管理器.py", line 25, in <module>
   raise Exception('error occur while handling file')
Exception: error occur while handling file
'''

8.何时应该编写上下文管理器
a.资源清理
b.避免重复
i.传播异常:__exit__方法可以向流程链上传播异常,这是通过返回False实现的。

class MyOpen(object):
    def __init__(self, file_name, file_mode):
        self.file_name = file_name
        self.file_mode = file_mode

    def __enter__(self):
        print('这是 __enter__ 函数')
        self.file = open(self.file_name, self.file_mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        :param exc_type:
        :param exc_val:
        :param exc_tb:
        :return:
        """
        print('这是 __exit__ 函数')
        self.file.close()
        return False


with MyOpen('1.txt', 'r') as f:
    file_data = f.read()
    print(file_data)
    raise Exception('error occur while handling file')

'''
Traceback (most recent call last):
  File "C:\Users\dyc\PycharmProjects\scripts\with和上下文管理器\上下文管理器.py", line 26, in <module>
    raise Exception('error occur while handling file')
Exception: error occur while handling file
这是 __enter__ 函数
here is some text
这是 __exit__ 函数
'''

ii.终止异常:__exit__方法可以终止它所接收的异常,这是通过返回True实现的。

class MyOpen(object):
    def __init__(self, file_name, file_mode):
        self.file_name = file_name
        self.file_mode = file_mode

    def __enter__(self):
        print('这是 __enter__ 函数')
        self.file = open(self.file_name, self.file_mode)
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        """
        :param exc_type:
        :param exc_val:
        :param exc_tb:
        :return:
        """
        print('这是 __exit__ 函数')
        self.file.close()
        return True


with MyOpen('1.txt', 'r') as f:
    file_data = f.read()
    print(file_data)
    raise Exception('error occur while handling file')

'''
这是 __enter__ 函数
here is some text
这是 __exit__ 函数
'''

c.处理特定异常类:这个就是在__exit__方法中对异常类型进行判断,可以仅处理某类异常,或实现其他功能。
d.基于属性的异常处理
9.使用contextlib简化上下文管理器的实现
a.yield之前的代码相当于__enter__函数的内容、
b.yield之后的代码相当于__exit__函数的内容

 import contextlib

@contextlib.contextmanager
def handle_file(file_name):
    print(f'open file: {file_name}')
    yield
    print(f'close file: {file_name}')


with handle_file('1.txt') as f:
    print('process file')
    
'''
open file: 1.txt
process file
close file: 1.txt
'''
  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值