[python, CPython] GC behavior when throwing an exception

When you throw an exception in python (CPython), the frame that throws the exception is added to the frame that caught the exception. This makes the behavior of the reference count non-trivial and unintentionally extends the life of the object.

class Foo(Exception):
    def __init__(self):
        print 'construt'
    
    def __del__(self):
        print 'destruct'
    
    def raiseError(self):
        raise Exception()

def main ():
    print 'enter main'
    foo = Foo()
    try:
        foo.raiseError()
    except:
        print 'catch exception'
    foo = None
    print 'exit main'

try:
    main()
finally:
    print 'finish'

The output of the above code is as follows.

enter main
construt
catch exception
exit main
destruct
finish

As mentioned above, even if the foo object in main is intended to be released before'exit main', the life of foo is extended until the frame of main is released. This is because the frame inside the raiseError that threw the exception is kept in the frame inside the main, and the frame inside the raiseError holds self = foo.

Exception frames are released with sys.exc_clear ().

As a similar example, when trying-catch in a loop, the release timing of the object secured in the loop may be shifted by one loop. This is because the exception frame is released by the exception throw in the next loop.

http://stackoverflow.com/questions/8822418/object-not-freed-after-an-exception-raise-in-python-2-7

Recommended Posts

[python, CPython] GC behavior when throwing an exception
Check the behavior when assigning Python
Note when creating an environment with python
[python, multiprocessing] Behavior for exceptions when using multiprocessing
[Python] When an amateur starts machine learning
Behavior when saving python datetime object in MongoDB
Python exception handling
Python exception handling
When you get an error in python scraping (requests)