はい、GCは電話をかけています __del__
発電機のクリーンアップフック、それは GeneratorExit
発電機関数で発電機を終了する(呼び出すことによって generator.close()
).
これは、コンテキストマネージャーを意味します __exit__
メモリからジェネレーター関数がクリアされるたびにフックが呼び出されます。
最初にジェネレーターを手動で閉じることができます generator.close()
:
b.close()
質問
ジェネレーターをコルーチンとして使用して、タスクスケジューラのようなものを作成しています。以下のコードでは、 print cleanup
決定論的に。
私の相互作用から、オブジェクトをガベージコレクターにリリースすると、コンテキストマネージャーが終了するように思われます。しかし、私はGCのタイミングに頼るよりもよく知っています。それは本当にGCを呼んでいますか __exit__
それとも別のメカニズムですか?
どうすれば厳密に強制することができますか print 'cleanup'
?
>>> from contextlib import contextmanager
>>> @contextmanager
... def foo():
... print 'setup'
... try:
... yield
... finally:
... print 'cleanup'
...
>>> def bar():
... with foo():
... while True:
... yield 'bar'
...
>>> b = bar()
>>> b.next()
setup
'bar'
>>> b = None
cleanup
解決
はい、GCは電話をかけています __del__
発電機のクリーンアップフック、それは GeneratorExit
発電機関数で発電機を終了する(呼び出すことによって generator.close()
).
これは、コンテキストマネージャーを意味します __exit__
メモリからジェネレーター関数がクリアされるたびにフックが呼び出されます。
最初にジェネレーターを手動で閉じることができます generator.close()
:
b.close()
他のヒント
ジェネレーターを出させる必要があります。ジェネレーターの性質が永遠に見える場合、Gen.Throw()を使用して、発電機の例外を提起できます。
実際、私はジェネレーターの仕様を見たばかりで、それらはまさにこれを行う方法()を持っています(ジェネレーター内でgeneratorexit()例外が提起されます。したがって、gen.close()に電話してください。コンテキストマネージャーはすべてを呼び出します 出口 方法。ジェネレーターは例外を食べるので、トライブロックでclose()コールをラップする必要はありません。
>>> b= bar()
>>> b.next()
setup
'bar'
>>> b.close()
cleanup
>>>