是的,您可以在发生器中使用with
语句而不会出现问题。 Python将正确处理上下文,因为当收集垃圾时,生成器将被关闭。
在发电机发电机垃圾回收时,一个GeneratorExit
引发异常,因为它会在那个时候被关闭:
>>> from contextlib import contextmanager
>>> @contextmanager
... def somecontext():
... print 'Entering'
... try:
... yield None
... finally:
... print 'Exiting'
...
>>> def values():
... with somecontext():
... yield 1
... yield 2
...
>>> next(values())
Entering
Exiting
1
这是PEP 342,在关闭发电机引发异常的一部分。如果Jython没有关闭生成器,收获没有引用的生成器应该总是关闭该生成器。我认为这是一个bug。
参见规格概要的点4和5:
添加发电机迭代器close()
方法,其中在生成器被暂停的点引发GeneratorExit
。如果 发电机然后提高StopIteration
(通过正常退出,或 由于已关闭)或GeneratorExit
(通过不捕获 的例外),close()
返回给它的调用者。如果发电机 产生一个值,则产生一个RuntimeError
。如果发生器 引发任何其他异常,它将传播给调用者。 close()
如果由于 异常或正常退出而发生器已经退出,则不执行任何操作。
添加支持以确保在发生器 垃圾回收时调用close()
。然后
唯一要注意的是,在Jython中,IronPython和PyPy垃圾收集器不能保证离开解释之前运行。如果这对您的应用程序非常重要,则可以明确关闭生成器:
gen = values()
next(gen)
gen.close()
或明确触发垃圾回收。
我无法明确地在langdoc中找到保证这种行为的任何语句。正如我在这个问题中写的那样,我意识到在普通实践中会出现这种情况,但依靠它是否安全?我应该向Jython人员报告缺乏这种功能吗? – Dolda2000 2015-03-13 19:35:02
@ Dolda2000:我正在给你一个测试用例来展示;听起来像Jython在这方面有一个错误。 – 2015-03-13 19:35:36
我已经有了一个测试用例,表明它在CPython上工作,但是我真正要问的是它应该被认为是定义良好还是仅仅是CPython实现的意外。我在问,因为我正在建立一个系统,我希望真正依靠这种行为,而且它的正确性非常重要。 – Dolda2000 2015-03-13 19:37:09