Generic Exception Handling in Python the “Right Way”

前端 未结 6 1149
夕颜
夕颜 2020-12-23 00:07

Sometimes I find myself in the situation where I want to execute several sequential commands like such:

try:
    foo(a, b)
except Exception, e:
    baz(e)
tr         


        
相关标签:
6条回答
  • 2020-12-23 00:31

    If they're simple one-line commands, you can wrap them in lambdas:

    for cmd in [
        (lambda: foo (a, b)),
        (lambda: bar (c, d)),
    ]:
        try:
            cmd ()
        except StandardError, e:
            baz (e)
    

    You could wrap that whole thing up in a function, so it looked like this:

    ignore_errors (baz, [
        (lambda: foo (a, b)),
        (lambda: bar (c, d)),
    ])
    
    0 讨论(0)
  • 2020-12-23 00:34

    The best approach I have found, is to define a function like such:

    def handle_exception(function, reaction, *args, **kwargs):
        try:
            result = function(*args, **kwargs)
        except Exception, e:
            result = reaction(e)
        return result
    

    But that just doesn't feel or look right in practice:

    handle_exception(foo, baz, a, b)
    handle_exception(bar, baz, c, d)
    
    0 讨论(0)
  • 2020-12-23 00:38

    In your specific case, you can do this:

    try:
        foo(a, b)
        bar(c, d)
    except Exception, e:
        baz(e)
    

    Or, you can catch the exception one step above:

    try:
        foo_bar() # This function can throw at several places
    except Exception, e:
        baz(e)
    
    0 讨论(0)
  • 2020-12-23 00:39

    You could use the with statement if you have python 2.5 or above:

    from __future__ import with_statement
    import contextlib
    
    @contextlib.contextmanager
    def handler():
        try:
            yield
        except Exception, e:
            baz(e)
    

    Your example now becomes:

    with handler():
        foo(a, b)
    with handler():
        bar(c, d)
    
    0 讨论(0)
  • 2020-12-23 00:40

    If this is always, always the behaviour you want when a particular function raises an exception, you could use a decorator:

    def handle_exception(handler):
        def decorate(func):
            def call_function(*args, **kwargs):
                try:
                    func(*args, **kwargs)
                except Exception, e:
                    handler(e)
            return call_function
        return decorate
    
    def baz(e):
        print(e)
    
    @handle_exception(baz)
    def foo(a, b):
        return a + b
    
    @handle_exception(baz)
    def bar(c, d):
        return c.index(d)
    

    Usage:

    >>> foo(1, '2')
    unsupported operand type(s) for +: 'int' and 'str'
    >>> bar('steve', 'cheese')
    substring not found
    
    0 讨论(0)
  • 2020-12-23 00:45

    You could try something like this. This is vaguely C macro-like.

    class TryOrBaz( object ):
        def __init__( self, that ):
            self.that= that
        def __call__( self, *args ):
            try:
                return self.that( *args )
            except Exception, e:
                baz( e )
    
    TryOrBaz( foo )( a, b )
    TryOrBaz( bar )( c, d )
    
    0 讨论(0)
提交回复
热议问题