blanket except clause -- best practice?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • George Young

    blanket except clause -- best practice?

    [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(S tandardError): pass
    class OperationalErro r(StandardError ): pass

    try:
    stuff
    except _pg.error, msg:
    raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
    except:
    raise OperationalErro r, "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 OperationalErro r, "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
  • Boris Boutillier

    #2
    Re: blanket except clause -- best practice?

    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

    On Tue, 28 Oct 2003 12:21:54 -0500, George Young wrote:
    [color=blue]
    > [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(S tandardError): pass
    > class OperationalErro r(StandardError ): pass
    >
    > try:
    > stuff
    > except _pg.error, msg:
    > raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
    > except:
    > raise OperationalErro r, "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 OperationalErro r, "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[/color]

    Comment

    • Skip Montanaro

      #3
      Re: blanket except clause -- best practice?


      George> class DatabaseError(S tandardError): pass
      George> class OperationalErro r(StandardError ): pass

      George> try:
      George> stuff
      George> except _pg.error, msg:
      George> raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
      George> except:
      George> raise OperationalErro r, "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 OperationalErro r, "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 OperationalErro r, \
      "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 OperationalErro r 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

      Comment

      • John J. Lee

        #4
        Re: blanket except clause -- best practice?

        George Young <gry@ll.mit.edu > writes:
        [color=blue]
        > [python 2.3.2, SuSE Linux 8.2, x86][/color]
        [...][color=blue]
        > try:
        > stuff
        > except _pg.error, msg:
        > raise DatabaseError, "error '%s' in '%s'" % ( msg, sql )
        > except:
        > raise OperationalErro r, "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:[/color]

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


        John

        Comment

        Working...