[Python-ideas] Deterministic iterator cleanup
Ronan Lamy
ronan.lamy at gmail.com
Fri Oct 21 15:20:55 EDT 2016
Le 21/10/16 à 14:35, Paul Moore a écrit :
>
> [1] As I understand it. CPython's refcounting GC makes this a
> non-issue, correct?
Wrong. Any guarantee that you think the CPython GC provides goes out of
the window as soon as you have a reference cycle. Refcounting does not
actually make GC deterministic, it merely hides the problem away from view.
For instance, on CPython 3.5, running this code:
#%%%%%%%%%
class some_resource:
def __enter__(self):
print("Open resource")
return 42
def __exit__(self, *args):
print("Close resource")
def some_iterator():
with some_resource() as s:
yield s
def main():
it = some_iterator()
for i in it:
if i == 42:
print("The answer is", i)
break
print("End loop")
# later ...
try:
1/0
except ZeroDivisionError as e:
exc = e
main()
print("Exit")
#%%%%%%%%%%
produces:
Open resource
The answer is 42
End loop
Exit
Close resource
What happens is that 'exc' holds a cyclic reference back to the main()
frame, which prevents it from being destroyed when the function exits,
and that frame, in turn, holds a reference to the iterator, via the
local variable 'it'. And so, the iterator remains alive, and the
resource unclosed, until the next garbage collection.
More information about the Python-ideas
mailing list