从内部使用语句和__exit__方法生成上下文管理器

Łuk*_*ski 10 python generator contextmanager

请考虑使用Python 2.x代码段.

from __future__ import print_function


class myfile(file):
    def __exit__(self, *excinfo):
        print("__exit__ called")
        super(myfile, self).__exit__(*excinfo)


def my_generator(file_name):
    with myfile(file_name) as fh:
        for line in fh:
            yield line.strip()


gen = my_generator('file.txt')
print(next(gen))
print("Before del")
del gen
print("After del")
Run Code Online (Sandbox Code Playgroud)

此脚本的输出(给定file.txt有多行)是:

Line 1 from file
Before del
__exit__ called
After del
Run Code Online (Sandbox Code Playgroud)

__exit__特别感兴趣.

什么触发了他的方法的执行?对于我们所知道的,代码从未离开过with语句(它在yield语句后"停止" 并且从未继续).__exit__当发电机的参考计数降至0时,是否保证会被调用?

use*_*ica 4

在回收生成器对象时,Python 会调用其close方法,如果该方法尚未执行完毕,则会GeneratorExit在最后一个方法处引发异常。yield当它GeneratorExit传播时,它会触发__exit__您使用的上下文管理器的方法。

这是在 Python 2.5 中引入的,与 yield 表达式相同的 PEPsend。在此之前,您无法yield使用 atry来访问 a finally,并且如果with语句在 2.5 之前就已存在,您也无法访问yielda 。