标签:man 等等 obj 处理程序 自己 文件的 com 做了 als
在Python中, 总有一些需要"善后"的事情要做, 比如说打开文件后自动关闭文件描述符, 比如说想要显示的释放某种资源, 比如...
上面这种需求很常见的一个场景就是读取文件, 很方便的一种做法是使用with
语句来控制
with open(‘a.txt‘ ‘r‘) as f:
f.readline()
这样写的好处是, 在with
里边的代码块执行完毕后, 会自动的关闭关闭文件. 而且这种写法可读性高, 犯错的几率也会变小.
那么, 包含with
的代码块在执行的时候都做了什么呢? 它的执行过程又是怎样的呢?
__enter__()
方法with
语句中设置了as
目标对象, 将__enter__()
返回的返回值赋给目标对象with
中的代码块__exit__()
方法, 如果with
中代码块中有异常, 那么会将exception_type, exception_value, traceback
传给__exit__()
, 如果其返回False
那么异常会被重新抛出, 否则异常被挂起, 程序继续执行OK, 那么, 什么是上下文管理器呢?
上下文管理器是一个对象, 它定义了程序在执行过程中的上下文, 处理程序的运行和退出, 实现了上下文管理协议, 即在对象中定义__enter__()
和__exit__()
方法
简单讲, 就是实现了__enter__()
和__exit__()
两个方法的对象, 我们都可以称之为上下文管理器
例如, 自己实现一个HTML标签上下文管理器
class HTMLContextManager(object):
def __init__(self, tag):
self._tag = tag
def __enter__(self):
print(‘<{}>‘.format(self._tag))
def __exit__(self, exception_type, exception_value, traceback):
print(‘</{}>‘.format(self._tag))
return False
with HTMLContextManager(‘h1‘):
print(‘I am body‘)
输出结果如下
<h1>
I am body
</h1>
可以说是非常的方便了, 在实际的应用当中, 可以把上下文管理器用作锁的控制, 文件的打开关闭, 异常处理等等, 在__enter__()
方法中实现资源分配, 预处理工作, 在__exit__()
方法中实现资源释放, 善后工作
但是, 如果想把一个函数对象包装成一个上下文管理器怎么办呢? Python的标准库提供了更加易用的contextlib
上下文管理工具模块, 它可以通过生成器实现, 不需要显示创建类以及__enter__()
和__exit__()
两个方法
示例:
@contextmanager
def html_context_manager(tag):
print(‘<{}>‘.format(tag))
yield
print(‘</{}>‘.format(tag))
with html_context_manager(‘h2‘):
print(‘I am body‘)
输出结果如下
<h2>
I am body
</h2>
比写一个类更加简便了! 但是这种写法, 如果with
代码块中的代码抛出了异常, 默认是向上抛出异常, 程序挂起的, 也就是类中__exit__()
方法返回False
还有一种比较好用的用法是把一个类包装成一个上下文管理器, 即
class MyClass(object):
def __init__(self):
pass
@contextmanager
def my_context_manager():
print(‘before call‘)
yield MyClass()
print(‘after call‘)
标签:man 等等 obj 处理程序 自己 文件的 com 做了 als
原文地址:https://www.cnblogs.com/spxcds/p/10204421.html