32

次のようないくつかのシーケンシャルコマンドを実行したい状況に陥ることがあります。

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

これと同じパターンは、例外を単に無視する必要がある場合に発生します。

これは冗長であると感じ、過度の構文により、コードを読み取るときに驚くほど追跡が困難になります。

Cでは、このタイプの問題をマクロで簡単に解決できたはずですが、残念ながら、これはストレートPythonでは実行できません。

質問:このパターンに遭遇したときに、コードのフットプリントを減らし、コードの可読性を高めるにはどうすればよいですか?

4

6 に答える 6

73

Python 2.5 以降を使用している場合は、次のwithステートメントを使用できます。

from __future__ import with_statement
import contextlib

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

あなたの例は次のようになります。

with handler():
    foo(a, b)
with handler():
    bar(c, d)
于 2008-09-24T19:05:58.007 に答える
15

これが常に、特定の関数が例外を発生させたときに常に必要な動作である場合は、デコレータを使用できます。

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)

使用法:

>>> foo(1, '2')
unsupported operand type(s) for +: 'int' and 'str'
>>> bar('steve', 'cheese')
substring not found
于 2008-09-25T13:31:32.513 に答える
4

lambda単純な 1 行のコマンドの場合は、 sでラップできます。

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

そのすべてを関数にまとめることができるので、次のようになります。

ignore_errors (baz, [
    (lambda: foo (a, b)),
    (lambda: bar (c, d)),
])
于 2008-09-24T19:04:59.803 に答える
3

私が見つけた最良のアプローチは、次のような関数を定義することです。

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

しかし、それは実際には正しく感じられないか、正しく見えません。

handle_exception(foo, baz, a, b)
handle_exception(bar, baz, c, d)
于 2008-09-24T19:05:17.227 に答える
3

このようなことを試すことができます。これは漠然と C マクロに似ています。

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 )
于 2008-09-24T20:15:09.993 に答える
-4

あなたの特定のケースでは、これを行うことができます:

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

または、1 ステップ上で例外をキャッチできます。

try:
    foo_bar() # This function can throw at several places
except Exception, e:
    baz(e)
于 2008-09-24T19:05:48.800 に答える