3

エラーを回避するために多くの方法を試したい場合は、次のように書くことができます。

try:

    try:
        trial_1()
    except some_error:
        try:
            trial_2()
        except some_error:
            try:
                trial_3()
            ...
    print "finally pass"

except some_error:
    print "still fail"

でも試行回数が多すぎて巣が多すぎてどうやってフラットに書けばいいの?

4

4 に答える 4

5

毎回同じ例外であれば、次のことができます

for task in (trial_1, trial_2, trial_3, ...):
    try:
        task()
        break
    except some_error:
        continue

それが成功したかどうかを知ることが重要である場合、それを追加する最も明確な方法はおそらく

successful = False
for task in (trial_1, trial_2, trial_3, ...):
    try:
        task()
        successful = True
        break
    except some_error:
        continue
if successful:
    ...
else:
    ...
于 2013-02-21T02:04:17.573 に答える
1

これを複数回行う必要がある場合は、Hyperboreus と他の人が関数として提供した回答をまとめることができます。

def first_success(*callables):
    for f in callables:
        try:
            return f()
        except Exception as x:
            print('{} failed due to {}'.format(f.__name__, x))
    raise RuntimeError("still fail")

次に、必要なのは次のとおりです。

first_success(trial_1, trial_2, trial_3, trial_4)

logging.infoそれらの代わりに例外が必要な場合print、またはそれらを完全に無視する場合、またはそれらを追跡し、例外のリストを戻り値および/または例外に属性として添付するなどの場合、これを変更する方法はかなり明白なはずです.

関数に引数を渡したい場合、それはそれほど明白ではありませんが、それでも非常に簡単です。インターフェイスがどうあるべきかを決めるだけです。最初の引数として callable のシーケンスをとり、その後にすべての callable の引数をとります:

first_success((trial_1, trial_2, trial_3, trial_4), 42, spam='spam')

簡単だ:

def first_success(callables, *args, **kwargs):
    for f in callables:
        try:
            return f(*args, **kwargs)
        except Exception as x:
            print('{} failed due to {}'.format(f.__name__, x))
    else:
        raise RuntimeError("still fail")

常にこのパターンが必要なわけではないが、まったく同じではないものがたくさん必要な場合は、代わりに、任意の関数をtry. 私は実際にこれを6回構築しましたが、この関数を不要にするコードを書くためのよりpythonicな方法があることに気付きました。あなたはそれのより良い使い方を見つけるかもしれません:

def tried(callable, *args, **kwargs):
    try:
        return (callable(*args, **kwargs), None)
    except Exception as x:
        return (None, x)

、 などの高階関数を使用できるようmapになりましanyた。たとえば、map(tried, (trial_1, trial_2, trial_3, trial_4))4 つの非スロー関数のシーケンスを提供(f(x[0]) if x[1] is None else x for x in tried_sequence)し、Python で Haskell モナド チュートリアルを実行できます。これは、両方の Python プログラマーを作成するための良い方法です。 Haskell プログラマーはあなたを嫌っています。

于 2013-02-21T02:47:07.403 に答える
1

a) 各試行が異なり、b) すべてが同じエラーをスローし (コードが示しているため)、c) すべての試行関数の名前を知っていると仮定します。

for t in (trial_1, trial_2, trial_3, trial_4):
    try:
        t()
        # if we succeed, the trial is over
        break
    except some_error:
        continue

これはすべての試行をループし、予想されるエラーの場合は続行し、試行が成功した場合は停止し、その他の例外をスローします。それはあなたのサンプルコードと同じ動作だと思います。

于 2013-02-21T02:06:46.697 に答える
1

あなたはこれを行うことができます:

def trial1 (): 42 / 0
def trial2 (): [] [42]
def trial3 (): 'yoohoo!'
def trial4 (): 'here be dragons'

for t in [trial1, trial2, trial3, trial4]:
    print ('Trying {}.'.format (t.__name__) )
    try:
        t ()
        print ('Success')
        break
    except Exception as ex:
        print ('Failed due to {}'.format (ex) )
else:
    print ('Epic fail!')

出力は次のとおりです。

Trying trial1.
Failed due to division by zero
Trying trial2.
Failed due to list index out of range
Trying trial3.
Success
于 2013-02-21T02:07:37.217 に答える