سؤال

أنا أصنع شيئًا مثل جدولة المهام باستخدام المولدات مثل coroutines. في الكود أدناه ، أحتاج إلى تنفيذ 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
>>>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top