Exceptions and Object Destruction (was: Problem with apsw and garbage collection)
Mike Kazantsev
mk.fraggod at gmail.com
Sun Jun 14 01:55:09 EDT 2009
On Fri, 12 Jun 2009 18:33:13 -0400
Nikolaus Rath <Nikolaus at rath.org> wrote:
> Nikolaus Rath <Nikolaus at rath.org> writes:
> > Hi,
> >
> > Please consider this example:
> [....]
>
> I think I managed to narrow down the problem a bit. It seems that when
> a function returns normally, its local variables are immediately
> destroyed. However, if the function is left due to an exception, the
> local variables remain alive:
>
...
>
> Is there a way to have the obj variable (that is created in dostuff())
> destroyed earlier than at the end of the program? As you can see, I
> already tried to explicitly call the garbage collector, but this does
> not help.
Strange thing is that no one suggested contextlib, which made _exactly_
for this purpose:
#!/usr/bin/env python
import gc
class testclass(object):
def __init__(self):
self.alive = True # just for example
print "Initializing"
def __del__(self):
if self.alive:
# try..except wrapper would suffice here,
# so destruction won't raise ex, if already done
print "Destructing"
self.alive = False
def __enter__(self): pass
def __exit__(self, ex_type, ex_val, ex_trace):
self.__del__()
if not ex_type is None:
raise RuntimeError(ex_val)
def dostuff(fail):
with testclass() as obj:
# some stuff
if fail:
raise TypeError
# some more stuff
print "success"
print "Calling dostuff"
dostuff(fail=False)
print "dostuff returned"
try:
print "Calling dostuff"
dostuff(fail=True)
except TypeError:
pass
gc.collect()
print "dostuff returned"
And it doesn't matter where you use "with", it creates a volatile
context, which destructs before anything else happens on higher level.
Another simplified case, similar to yours is file objects:
with open(tmp_path, 'w') as file:
# write_ops
os.rename(tmp_path, path)
So whatever happens inside "with", file should end up closed, else
os.rename might replace valid path with zero-length file.
It should be easy to use cursor with contextlib, consider using
contextmanager decorator:
from contextlib import contextmanager
@contextmanager
def get_cursor():
try:
cursor = conn.cursor()
yield cursor
except Exception as ex: raise ex
finally: cursor.close()
with get_cursor() as cursor:
# whatever ;)
--
Mike Kazantsev // fraggod.net
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 205 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20090614/c323fd4f/attachment-0001.sig>
More information about the Python-list
mailing list