8

ジェネレーターをコルーチンとして使ってタスクスケジューラーのようなものを作っています。以下のコードでは、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
4

2 に答える 2

6

はい、GC は__del__ジェネレーターのクリーンアップ フックを呼び出しています。これGeneratorExitにより、ジェネレーター関数で a が発生し、ジェネレーターが終了します ( を呼び出すことによりgenerator.close())。

これは__exit__、ジェネレーター関数がメモリからクリアされるたびに、コンテキスト マネージャー フックが呼び出されることを意味します。

最初にジェネレーターを自分で手動で閉じることができますgenerator.close()

b.close()
于 2013-11-06T23:37:25.197 に答える
2

ジェネレーターを終了させる必要があります。ジェネレーターの性質が永久に見える場合は、gen.throw() を使用してジェネレーターで例外を発生させることができます。

実際、ジェネレーターの仕様を見たところ、まさにこれを行うメソッド close() があります (ジェネレーター内で GeneratorExit() 例外が発生します)。すべてのコンテキスト マネージャーはexitメソッドを呼び出しますが、ジェネレーターは例外を食べるので、try ブロックで close() 呼び出しをラップする必要はありません。

>>> b= bar()
>>> b.next()
setup
'bar'
>>> b.close()
cleanup
>>>
于 2013-11-06T23:37:33.847 に答える