Bug in Python 1.5.2 exception handling?
Dave Cole
djc at itga.com.au
Wed Dec 15 18:42:14 EST 1999
Tim> [Dave Cole]
Tim> > It looks like function locals are not deleted if that function is
Tim> > terminated by an exception.
Tim>
Tim> That's true, but it's not a bug: Python doesn't define the
Tim> lifetime of objects. CPython is much more predictable than
Tim> JPython in this respect-- thanks to using refcounts --but you
Tim> still rely on it at your own risk. In the case of a function
Tim> that terminates due to exception, the locals are still very much
Tim> alive, because they *can* be reached via the traceback object
Tim> (from which the chain of stack frames can be reached, from which
Tim> the locals can be reached).
Der... I forgot about the traceback stuff. I have even written some
code to give nice pretty HTML formatted tracebacks for the Python CGI
stuff I have written here.
A trap for young players if ever there was one.
Tim> Change your loop to:
Tim>
Tim> for val in range(3):
Tim> try:
Tim> check_raise(val)
Tim> except:
Tim> try:
Tim> raise "dummy"
Tim> except:
Tim> pass
Tim>
Tim> and you'll see that the 'raise "dummy"' has the same effect.
And in doing so, you end up dropping all references to the previous
traceback. Not really what I was after, but oh well.
The reason that I was worried about this was that I am doing some
database stuff using my Sybase module:
plug: http://www.itga.com.au/~djc/sybase.html
I wanted to automatically rollback a transaction when an exception was
raised during processing. I made a class like this:
class Transaction:
def __init__(self, db, name):
self.db = db
self.name = name
self.db.execute('begin transaction %s' % (self.name,))
self.commit = 0
def __del__(self):
if self.commit:
self.db.execute('commit transaction %s' % (self.name,))
else:
self.db.execute('rollback transaction %s' % (self.name,))
Then I thought that all I would have to do was:
def something_or_other(self):
tran = Transaction(self.db, 'update_id')
# lots o' database stuff
tran.commit = 1
I suppose it will still work for the rollback case, but just not when
I expect it to.
Tim> > class c:
Tim> > def __init__(self, val):
Tim> > self.val = val
Tim> > def __del__(self):
Tim> > print val, 'deleted'
Tim>
Tim> You really want
Tim>
Tim> print self.val, 'deleted'
I was really quite determined to confuse myself.
- Dave
More information about the Python-list
mailing list