Python/上下文管理器
外观
< Python
程序应当对获取的资源使用后释放,否则会造成资源泄露。
资源管理基础
[编辑]常见办法是open()...close()
这样的函数:
f = open(filename)
# ...
f.close()
问题是如果代码块抛出了异常或者早期return,那么不会调用资源释放语句。为此,可以用try...finally
语句:
f = open(filename)
try:
# ...
finally:
f.close()
缺点是手工释放资源有可能忘记写了,而且资源释放语句离资源获取的距离可能太远。
自动化的语句with
可以处理File
这样的上下文管理器类型的资源释放:
with open(filename) as f:
# ...
实现细节
[编辑]可用于with
的上下文管理器类型(context manager types)必须实现__enter__()
, __exit__()
函数。
__init__()
在创建对象时被调用,__enter__()
在with
语句种被调用返回一个值(如对象、句柄)。
a_cm = A()
with a_cm as a:
...
注意事项
[编辑]上下文,不是作用域
[编辑]with
语句不构成作用域。
生成器
[编辑]生成器持续调用时,可能资源已经释放了,从而抛出异常。
with open(filename) as f:
lines = (line.rstrip('\n') for line in f)
不是RAII
[编辑]资源获取即初始化(RAII)不适用于Python这样的垃圾回收语言。因为即使对象的引用计数为0,也不一定在什么时候被垃圾回收。所以,用finally更为可靠。
参考文献
[编辑]外部链接
[编辑]- Get With the Program as Contextmanager
- PyMOTW (Module of the Week): contextlib
- Markus Gattol: Context Manager