是的,您可以在發生器中使用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