python 上下文管理器(Context managers)

版权声明:随心所欲、无欲无求! https://blog.csdn.net/qq_32662595/article/details/85090821

上下文管理器允许你在有需要的时候,精确地分配和释放资源。

需求:
有两个需要结对执行的相关操作,然后还要在它们中间放置一段代码。

with open('some_file', 'w') as opened_file:
    opened_file.write('Hola!')

等价于:

file = open('some_file', 'w')
try:
    file.write('Hola!')
finally:
    file.close()

上下文管理器的一个常见用例,是资源的加锁和解锁,以及关闭已打开的文件。

基于类的实现

自定义开启文件的上下文管理器

一个上下文管理器的类,最起码要定义__enter____exit__方法。

class  File(object):
    def __init__(self, file_name, method):
        self.file_obj = open(file_name, method)
    def __enter__(self):
        return self.file_obj
    def __exit__(self, type, value, traceback):
        self.file_obj.close()

在with中使用自定义的管理器:

with File(fileName ,method) as opened_file:
    opened_file.write('Hola!')

操作步骤

  1. with语句先暂存了File类的__exit__方法
  2. 然后它调用File类的__enter__方法
  3. __enter__方法打开文件并返回给with语句
  4. 打开的文件句柄被传递给opened_file参数
  5. 使用.write()来写文件
  6. with语句调用之前暂存的__exit__方法
  7. __exit__方法关闭了文件

异常处理:

  1. 它把异常的type,value和traceback传递给__exit__方法
  2. 它让__exit__方法来处理异常
  3. 如果__exit__返回的是True,那么这个异常就被优雅地处理了
  4. 如果__exit__返回的是True以外的任何东西,那么这个异常将被with语句抛出。
class File(object):
    def __init__(self, file_name, method):
        self.file_obj = open(file_name, method)
    def __enter__(self):
        return self.file_obj
    def __exit__(self, type, value, traceback):
        print("Exception has been handled")
        self.file_obj.close()
        return True
        
with File(fileName, 'w') as opened_file:
    opened_file.undefined_function()

基于生成器的实现

用装饰器(decorators)和生成器(generators)来实现上下文管理器。Python有个contextlib模块专门用于这个目的。我们可以使用一个生成器函数来实现一个上下文管理器.

from contextlib import contextmanager

@contextmanager
def open_file(name):
    f = open(name, 'w')
    yield f
    f.close()
  1. Python解释器遇到了yield关键字。因为这个缘故它创建了一个生成器而不是一个普通的函数。
  2. 因为这个装饰器,contextmanager会被调用并传入函数名(open_file)作为参数。
  3. contextmanager函数返回一个以GeneratorContextManager对象封装过的生成器。
  4. GeneratorContextManager被赋值给open_file函数,我们实际上是在调用GeneratorContextManager对象。

猜你喜欢

转载自blog.csdn.net/qq_32662595/article/details/85090821
今日推荐