[Zope3-dev] Please, no bare 'except:' clauses!

Jeremy Hylton jeremy@zope.com (Jeremy Hylton)
Mon, 11 Nov 2002 12:50:27 -0500


>>>>> "SH" == Shane Hathaway <shane@zope.com> writes:

  SH> 1) Don't let DatabaseErrors be so special any more.  Currently,
  SH> we want ConflictErrors to propagate, in order to prevent
  SH> inconsistent data from being committed, and to give the app an
  SH> opportunity to retry.  But excessive exception catching ought
  SH> not to be so catastrophic.  I think any attempt to write or
  SH> commit after a ConflictError has occurred should result in
  SH> another ConflictError, since the data being written is generated
  SH> from inconsistent data.  AFAICT this would eliminate the need to
  SH> make DatabaseErrors special, and would only change ZODB.

I agree that a transaction that gets a conflict should be impossible
to commit.  It should get marked as "aborting" and any future attempt
to commit it will raise ConflictError again.

This is sufficient for dealing with sloppy exception handling,
though.  If the transaction is read-only and the except clause
swallows a ReadConflictError, the app may never find out that a
consistency problem occurred.

Thinking more... I suppose a Connection could have a per-transaction
marker that says it has detected a read conflict.  If the marker is
set, it could refuse to load any more objects.  That sounds a bit
draconian.  I'm not sure what makes sense.

  SH> 2) Add a subclass of Exception that does not get caught by
  SH> normal "except" clauses.  "SlipperyExceptions" only get caught
  SH> by exception handlers that specifically catch
  SH> SlipperyExceptions.  This could mess up code that uses "except:"
  SH> where it should be using "finally:".  It would require a change
  SH> to Python.

Here's a variant suggestion.  Make POSException inherit from
Exception.  Use "except StandardError:" as the catch all exception
handler in most circumstances.  Since POSException wouldn't inherit
from StandardError, the app would work as expected.

There are very few places where bare except is needed.  At least some
of those places, the bare except is in place because it's very hard to
tell what exception Python might raise (calling int() is an example).
In cases like that, the StandardError solution is a good one.

Jeremy