cleanup after exceptions

Peter Otten __peter__ at web.de
Thu Dec 18 15:49:16 EST 2003


Jp Calderone wrote:

> On Thu, Dec 18, 2003 at 07:11:12PM +0000, Padraig at Linux.ie wrote:
>> Hi,
>> 
>> I'm a little confused why objects
>> are not deleted after they go
>> out of scope due to an exception?
> 
>   Because objects don't go out of scope.  Only variables do.  Objects
>   remain
> "alive" as long as there are any references to them.
> 
>> 
>> For e.g.
>> 
>> >>> import time
>> >>>
>> >>> def f():
>> >>>     myfile=open("file.test","w")
>> >>>     myfile.write("not flushed\n")
>> >>>     exception=throw
>> >>>
>> >>> f()
>> >>> time.sleep(10)
>> 
>> 
>> The file is not written/closed until
>> the python interpreter exits.
>> The same thing applies to other objects.
> 
>   In this case, the traceback still holds a reference to the frame from
> which the exception was raised, which itself holds a reference to all the
> locales from that function.
> 
>   Calling sys.exc_clear() (possibly followed by gc.collect()) should force
> the cleanup you expect.

I tried out your recipe, but with no luck:

Python 2.3.2 (#1, Oct 21 2003, 10:03:19)
[GCC 3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> class T:
...     def __del__(self):
...             print "now i'm gone"
...
>>> def f():
...     t = T()
...     raise Exception
...
>>> import sys, gc
>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 3, in f
Exception
>>> sys.exc_clear()
>>> gc.collect()
0

The only way to clear the reference I've found so far is a bit unorthodox:

>>> raise Exception
now i'm gone
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
Exception

There seems to be some dark corner of the exception infrastructure that
exc_clear() doesn't touch.

However, I think it's about time to direct the OP to the solution of the
"real" problem, i. e. ensuring that a resource is released when an
exception occurs:

>>> def g():
...     t = T()
...     try:
...             raise Exception
...     finally:
...             del t
...
>>> g()
now i'm gone
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<stdin>", line 4, in g
Exception
>>>

Whether immediate garbage collection occurs, is an implementation detail.
The code will be more portable if try...finally is used in such cases.

Peter






More information about the Python-list mailing list