try/finally question

Paul Rubin phr-n2002b at NOSPAMnightsong.com
Wed Jul 10 03:55:30 EDT 2002


Is there a reasonable way to skip around a "finally" clause?

E.g, suppose I have a simple "db" (database) object that supports
these operations:

   db.begin()  # begin a transaction  (locks the database)
   db.do_action()   # update some record or whatever
   db.commit()   # commit the actions and close the transaction
   db.cancel()   # discard the actions and close the transaction

db.commit() and db.cancel() both release the lock of course.
Also, doing db.cancel() with no transaction open is a no-op.

So the obvious way to use it is:

   try:
      db.begin()
      x = db.do_action(first_thing)
      y = db.do_action(second_thing)
      db.commit()
   finally:
      db.cancel()

The trouble is db.cancel() is an ordinary method call--it's not atomic
in the interpreter.  It can be interrupted and blast out of the
finally block before finishing, and then control returns to some
higher level with the database still locked.

In a C program I'd use sigsetmask to turn off interrupts during the
critical section, but Python doesn't have that.  All I can think of
are yet more try/finally blocks, which is ugly and which still might
not close all the gaps.  In particular, I don't know whether calling a
method from a finally block is guaranteed to execute the first Python
statement in the method, if an interrupt comes at that exact instant.

What's the right way to handle this?

Thanks.



More information about the Python-list mailing list