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