8

私はよくこのようなことをしたいと思っています、私はこのようなことを除いて何かを試してみました

item= get_item()
try:
    do_work(item)
except SomeError as err:
    if err.code == 123:
        do_something(item)
    else:
        # Actually I don't want to do something with this error code... I want to handle in 'except'
except:
    put_back(item)
    raise

except他から下のブロックに上がる方法はありますか?(continueいいでしょう)私は次のようなきれいではないことをすることになります

item= get_item()
try:
    try:
        do_work(item)
    except SomeError as err:
        if err.code == 123:
            do_something(item)
        else:
            raise
 except:
     put_back(item)
     raise

とにかくそれをすることはありますか?

4

4 に答える 4

9

最近の十分な数のPythonバージョン(2.5以降)を使用している場合は、代わりにコンテキストマネージャーの使用に切り替える必要があります。

class WorkItemContextManager(object):
    def __enter__(self):
        self.item = get_item()
        return self.item

    def __exit__(self, exc_type, exc_value, tb):
        if exc_type is not None:
            if exc_type is SomeError and exc_value.code == 123:
                do_something(self.item)
                return True  # Exception handled
            put_back(self.item)

それで:

with WorkItemContextManager() as item:
    do_work(item)

__exit__例外が処理された場合、メソッドはTrueを返すことができます。Noneを返すと、代わりにブロックで発生した例外が再発生しwithます。

finallyそうでない場合は、代わりにブロックを探しています。

item = get_item()
try:
    do_work(item)
    item = None
except SomeError as err:
    if err.code == 123:
        do_something(item)
        item = None
finally:
    if item is not None:
        put_back(item)

スイートが完了する、例外が発生したときに、スイートfinallyが実行されることが保証されます。基本的に、スイートにすべてが正常に完了したことを伝えるように設定することで、元に戻す必要はありません。try:itemNonefinally

ハンドラーはfinallyブランケットハンドラーから引き継ぎますexcept。で例外が発生した場合do_workitemは[なし]に設定されません。SomeErrorハンドラーが例外をキャッチしない場合、または123でerr.codeない場合itemも、Noneに設定されないため、put_back(item)メソッドが実行されます。

于 2012-09-11T17:16:02.903 に答える
2

私の提案は、制御したいエラーをスローするメソッドをラップする関数(または一連の関数)を作成することです。何かのようなもの...

def wrapper(arg):
    try:      
        do_work(arg)
    except SomeError as e:
        if e.code == 123:
           do_something(item)
           # Other possible cleanup code
        else:
           raise

...そして、あなたがそれを呼びたいとき...

try:
    wrapper(arg)
except SomeError as e:
    put_back(arg)
于 2012-09-11T17:31:31.040 に答える
2

コンテキストマネージャーは優れていますが、他の場所でロジックを再利用しない単純なケースでは、少し重い場合があります。

複数のブロックを作成する代わりに、単一のブロックexcept内で例外をテストすることができます。except

item= get_item()
try:
    do_work(item)
except Exception as err:
    if isinstance(err, SomeError) and err.code == 123:
        do_something(item)
    else:
        put_back(item)
        raise

とにかく、これはコンテキストマネージャの__exit__メソッドが最終的にどのように見えるかとほぼ同じであることに注意してください。

実際に属するコードがfinallyここで終了しないことに注意してください。

于 2017-01-02T18:52:31.407 に答える
1

try-exceptフローの目的を覚えておくとよいでしょう。また、その利点の1つは、ステータス変数やステータスチェックの必要がなくなることです。

if not foo:
    # do something

また、Exceptionクラスは特定の種類のエラーを表す必要があります。例外ブロックのエラーの種類についてさらに決定する必要がある場合は、クラスがプログラムの状態を表すのに十分なほど具体的でないことを示す良い兆候です。最善の策は、SomeErrorをサブクラス化し、最初のサブクラスのみをキャッチすることです。次に、SomeErrorの他のインスタンスは、ブロックを除いて2番目にフォールスルーします。

于 2012-09-11T17:24:42.457 に答える