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.
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to