如果生成器被垃圾收集,上下文管理器是否退出?
Is a context manager exited if a generator is garbage collected?
假设我们有一个像这样的简单生成器:
def generator():
with open('example.txt', 'r') as f:
yield f.readline()
yield f.readline()
并像这样使用它来获得单个 element/line:
line = next(generator())
一旦临时生成器对象被垃圾回收,上下文管理器是否关闭?
我们可以测试一下。答案是肯定的,关门了。
import contextlib
@contextlib.contextmanager
def tester():
try:
print("enter")
yield 42
finally:
print("exit")
def generator():
with tester() as m:
yield m
print(next(generator()))
结果:
enter
exit
42
with
语句与 try
语句具有相同的语义,除了 with
语句本身的主体之外还有一些额外的代码执行。来自 https://docs.python.org/3/reference/compound_stmts.html#the-with-statement"
The following code:
with EXPRESSION as TARGET:
SUITE
is semantically equivalent to:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
所以我们的 yield
表达式在 with
语句隐含的 try
语句中。
来自 https://docs.python.org/3/reference/expressions.html#yieldexpr
Yield expressions are allowed anywhere in a try construct. If the generator is not resumed before it is finalized (by reaching a zero reference count or by being garbage collected), the generator-iterator’s close() method will be called, allowing any pending finally clauses to execute.
with
语句隐含的 finally
子句显式调用上下文管理器的 __exit__
方法,该方法关闭文件。
假设我们有一个像这样的简单生成器:
def generator():
with open('example.txt', 'r') as f:
yield f.readline()
yield f.readline()
并像这样使用它来获得单个 element/line:
line = next(generator())
一旦临时生成器对象被垃圾回收,上下文管理器是否关闭?
我们可以测试一下。答案是肯定的,关门了。
import contextlib
@contextlib.contextmanager
def tester():
try:
print("enter")
yield 42
finally:
print("exit")
def generator():
with tester() as m:
yield m
print(next(generator()))
结果:
enter
exit
42
with
语句与 try
语句具有相同的语义,除了 with
语句本身的主体之外还有一些额外的代码执行。来自 https://docs.python.org/3/reference/compound_stmts.html#the-with-statement"
The following code:
with EXPRESSION as TARGET: SUITE
is semantically equivalent to:
manager = (EXPRESSION) enter = type(manager).__enter__ exit = type(manager).__exit__ value = enter(manager) hit_except = False try: TARGET = value SUITE except: hit_except = True if not exit(manager, *sys.exc_info()): raise finally: if not hit_except: exit(manager, None, None, None)
所以我们的 yield
表达式在 with
语句隐含的 try
语句中。
来自 https://docs.python.org/3/reference/expressions.html#yieldexpr
Yield expressions are allowed anywhere in a try construct. If the generator is not resumed before it is finalized (by reaching a zero reference count or by being garbage collected), the generator-iterator’s close() method will be called, allowing any pending finally clauses to execute.
with
语句隐含的 finally
子句显式调用上下文管理器的 __exit__
方法,该方法关闭文件。