blanket except clause -- best practice?

G

George Young

[python 2.3.2, SuSE Linux 8.2, x86]
I have a bunch of blanket "except:" clauses like:
[OK, it's not "my" code but I use it and it troubles me...]

class DatabaseError(StandardError): pass
class OperationalError(StandardError): pass

try:
stuff
except _pg.error, msg:
raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
except:
raise OperationalError, "internal error in '%s'" % sql


This accomplishes passing useful info, namely "sql", on with
the exception. Unfortunately it *loses* info in that upstream
has no way to know *which* exception triggered this or what args
it might have been given. I'm trying to think of a clean way
to improve this. I could do:

try:
stuff
except _pg.error, msg:
raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
except Exception, x:
raise OperationalError, "internal %s(%s) error in '%s'" (x.__class__,
x.args, sql)


Is there something more clear/portable/pythonic than this?
How do people handle this sort of fallback "except" clause?

-- George
 
B

Boris Boutillier

The following code do nothing:
import sys
try:
stuff
except:
type,val,tb = sys.exc_info()
raise type,val,tb

With this should be able to do what you want.

Boris
 
S

Skip Montanaro

George> class DatabaseError(StandardError): pass
George> class OperationalError(StandardError): pass

George> try:
George> stuff
George> except _pg.error, msg:
George> raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
George> except:
George> raise OperationalError, "internal error in '%s'" % sql

George> This accomplishes passing useful info, namely "sql", on with the
George> exception. Unfortunately it *loses* info in that upstream has
George> no way to know *which* exception triggered this or what args it
George> might have been given. I'm trying to think of a clean way to
George> improve this. I could do:

George> try:
George> stuff
George> except _pg.error, msg:
George> raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
George> except Exception, x:
George> raise OperationalError, "internal %s(%s) error in '%s'" (x.__class__, x.args, sql)

Perhaps you should simply reraise the original exception:

try:
stuff
except _pg.error, msg:
raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
except:
raise

The resulting traceback displayed may be lower level than you would like,
but at least no information about where the actual error occurred is lost.

You can also synthesize a new exception using the original stack frame:

try:
stuff
except _pg.error, msg:
raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
except Exception, x:
raise OperationalError, \
"internal %s(%s) error in '%s'" (x.__class__, x.args, sql), \
sys.exc_info()[2]

This uses the original traceback object (sys.exc_info()[2]), but raises it
with your OperationalError and error string, which can obviously include
object values not available at the actual point where the original exception
was raised. You could obviously include the first two values from
sys.exc_info() in your new exception as well.

Skip
 
J

John J. Lee

George Young said:
[python 2.3.2, SuSE Linux 8.2, x86] [...]
try:
stuff
except _pg.error, msg:
raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
except:
raise OperationalError, "internal error in '%s'" % sql


This accomplishes passing useful info, namely "sql", on with
the exception. Unfortunately it *loses* info in that upstream
has no way to know *which* exception triggered this or what args
it might have been given. I'm trying to think of a clean way
to improve this. I could do:

Just have an attribute of OperationalError that holds the exception
caught by the except:


John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,169
Messages
2,570,919
Members
47,459
Latest member
Vida00R129

Latest Threads

Top