When a generator is garbage-collected or explicitly closed (via the .close()
method), a GeneratorExit
exception is raised within the generator. You can catch this exception to perform manual cleanup if with
statements and the like aren't covering your use case. And you can ensure close
is called explicitly to avoid arbitrary cleanup delays when reference cycles are present (or you're on a non-CPython interpreter that uses a strategy other than reference counting for memory management).
So in your caller, you can change:
for record in my_multi_collector.collect():
... body goes here ...
to:
# At top of file
from contextlib import closing # Allows easy guarantee close behavior
# Replacing existing code
with closing(my_multi_collector.collect()) as results:
for record in records:
... body goes here ...
# When code dedents out of with, generator closed automatically, including on exception
Then if your with
statements within the generator aren't enough, you can explicitly wrap code with:
try:
... code goes here ...
except GeneratorExit:
... cleanup on early exit goes here ...
raise # Let exception continue bubbling to ensure cleanup finishes
finally:
... cleanup that must always run even when run to completion goes here ...
to perform any manual cleanup required (omitting except GeneratorExit:
or finally:
depending on what sort of cleanup conditions apply).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…