从上下文管理器的 with 语句和 __exit__ 方法中产生
Yielding from within with statement and __exit__ method of context manager
考虑以下 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")
此脚本的输出(给定 file.txt 有多行)是:
Line 1 from file
Before del
__exit__ called
After del
我对 __exit__
电话特别感兴趣。
是什么触发了他的方法的执行?据我们所知,代码从未离开 with
语句(它 "stopped" 在 yield
语句之后并且从未继续)。生成器的引用计数降为0时,是否保证__exit__
会被调用?
要添加到 ,with
块会在其中引发异常时中断。此异常被传递给为上下文创建的对象的 __exit__
方法。
file
class 似乎默默地传递了 GeneratorExit
异常,因为没有任何信号表明它。然而,如果你在你的 myfile.__exit__
方法中打印 argc
,你会看到上下文没有自然关闭:
class myfile(file):
def __exit__(self, *excinfo):
print("__exit__ called")
print(excinfo[0]) # Print the reason why the context exited
super(myfile, self).__exit__(*excinfo)
脚本输出:
Line 1 from file
Before del
__exit__ called
<type 'exceptions.GeneratorExit'>
After del
在回收生成器对象时,Python 调用其 close
方法,如果不是,则在最后一个 yield
点引发 GeneratorExit
异常已经执行完毕。当此 GeneratorExit
传播时,它会触发您使用的上下文管理器的 __exit__
方法。
这是在 Python 2.5、in the same PEP as send
and yield expressions 中引入的。在那之前,你不能在 try
和 finally
中 yield
,如果 with
语句在 2.5 之前就已经存在,你将无法 yield
里面一个也行。
考虑以下 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")
此脚本的输出(给定 file.txt 有多行)是:
Line 1 from file
Before del
__exit__ called
After del
我对 __exit__
电话特别感兴趣。
是什么触发了他的方法的执行?据我们所知,代码从未离开 with
语句(它 "stopped" 在 yield
语句之后并且从未继续)。生成器的引用计数降为0时,是否保证__exit__
会被调用?
要添加到 with
块会在其中引发异常时中断。此异常被传递给为上下文创建的对象的 __exit__
方法。
file
class 似乎默默地传递了 GeneratorExit
异常,因为没有任何信号表明它。然而,如果你在你的 myfile.__exit__
方法中打印 argc
,你会看到上下文没有自然关闭:
class myfile(file):
def __exit__(self, *excinfo):
print("__exit__ called")
print(excinfo[0]) # Print the reason why the context exited
super(myfile, self).__exit__(*excinfo)
脚本输出:
Line 1 from file
Before del
__exit__ called
<type 'exceptions.GeneratorExit'>
After del
在回收生成器对象时,Python 调用其 close
方法,如果不是,则在最后一个 yield
点引发 GeneratorExit
异常已经执行完毕。当此 GeneratorExit
传播时,它会触发您使用的上下文管理器的 __exit__
方法。
这是在 Python 2.5、in the same PEP as send
and yield expressions 中引入的。在那之前,你不能在 try
和 finally
中 yield
,如果 with
语句在 2.5 之前就已经存在,你将无法 yield
里面一个也行。