跳转到内容

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更为可靠。

参考文献

[编辑]