wake-up-neo.net

python-Ausnahmebedingung abfangen und Block weiterführen

Kann ich nach dem Auftreten einer Ausnahme wieder Try-Block ausführen? (Das Ziel ist, weniger zu schreiben) Zum Beispiel:

try:
    do_smth1()
except:
    pass

try:
    do_smth2()
except:
    pass

vs

try:
    do_smth1()
    do_smth2()
except:
    ??? # magic Word to proceed to do_smth2() if there was exception in do_smth1
32
igor

Nein, das kannst du nicht. Genau so hat Python seine Syntax. Wenn Sie einen Try-Block wegen einer Ausnahme beenden, gibt es keinen Weg zurück.

Was ist aber mit einer for-Schleife?

funcs = do_smth1, do_smth2

for func in funcs:
    try:
        func()
    except Exception:
        pass  # or you could use 'continue'

Beachten Sie jedoch, dass es eine schlechte Praxis ist, eine bloße except zu haben. Sie sollten stattdessen nach einer bestimmten Ausnahme fangen. Ich habe für Exception festgehalten, weil das so gut ist, wie ich kann, ohne zu wissen, welche Ausnahmen die Methoden auslösen könnten.

44
iCodez

Während die anderen Antworten und die akzeptierten Antworten korrekt sind und nur aus Gründen der Vollständigkeit und des Humors in echtem Code befolgt werden sollten, können Sie das Modul fuckitpy ( https://github.com/ajalt/fuckitpy ) ausprobieren.

Ihr Code kann wie folgt geändert werden:

@fuckitpy
def myfunc():
    do_smth1()
    do_smth2()

Der Aufruf von myfunc() würde do_smth2() auch dann aufrufen, wenn in do_smth1()) eine Ausnahme vorliegt.

Hinweis: Bitte versuchen Sie es mit not in einem echten Code, es ist Blasphemie

19
pankaj

Sie können erreichen, was Sie wollen, aber mit einer anderen Syntax. Sie können einen "finally" -Block nach dem try/except verwenden. Auf diese Weise führt python den Codeblock aus, unabhängig davon, ob die Ausnahme ausgelöst wurde oder nicht.

So was:

try:
    do_smth1()
except:
    pass
finally:
    do_smth2()

Wenn Sie do_smth2 () nur ausführen möchten, wenn die Ausnahme nicht ausgelöst wurde, verwenden Sie einen "else" -Block:

try:
    do_smth1()
except:
    pass
else:
    do_smth2()

Sie können sie auch in einer try/except/else/finally-Klausel mischen. Viel Spaß!

6
Lucas Ribeiro

Sie könnten durch Ihre Methoden iterieren ...

for m in [do_smth1, do_smth2]:
    try:
        m()
    except:
        pass
5
David Neale

eine Möglichkeit, wie Sie damit umgehen könnten, ist ein Generator. Anstatt die Funktion aufzurufen, geben Sie sie ab. Was auch immer der Generator verbraucht, kann das Ergebnis des Aufrufs in den Generator zurücksenden, oder ein Sentinel, falls der Generator ausfällt:

def consume_exceptions(gen):
    action = next(gen)
    while True:
        try:
            result = action()
        except Exception:
            # if the action fails, send a sentinel
            result = None

        try:
            action = gen.send(result)
        except StopIteration:
            # if the generator is all used up, result is the return value.
            return result

ein Generator, der damit kompatibel wäre, würde folgendermaßen aussehen:

def do_smth1():
    1 / 0

def do_smth2():
    print "YAY"

def do_many_things():
    a = yield do_smth1
    b = yield do_smth2
    yield "Done"
>>> consume_exceptions(do_many_things())
YAY

Beachten Sie, dass do_many_things() nicht call do_smth* ausführt, es gibt sie nur und consume_exceptions ruft sie in seinem Namen auf

Ich glaube nicht, dass du das machen willst. Die korrekte Verwendung einer try-Anweisung im Allgemeinen ist so genau wie möglich. Ich denke, es wäre besser zu tun:

try:
    do_smth1()
except Stmnh1Exception:
    # handle Stmnh1Exception

try:
    do_smth2()
except Stmnh2Exception:
    # handle Stmnh2Exception
1
rlms

Je nachdem, wo und wie oft Sie dies tun müssen, können Sie auch eine Funktion schreiben, die dies für Sie erledigt:

def live_dangerously(fn, *args, **kw):
    try:
        return fn(*args, **kw)
    except Exception:
        pass

live_dangerously(do_smth1)
live_dangerously(do_smth2)

Wie andere Antworten jedoch bereits festgestellt haben, ist das Vorhandensein eines Nullwerts except im Allgemeinen ein Zeichen, dass in Ihrem Code ein anderer Fehler vorliegt.

1
Dan

special_func Zur Vermeidung von Wiederholversuchen:

def special_func(test_case_dict):
    final_dict = {}
    exception_dict = {}

    def try_except_avoider(test_case_dict):

        try:
            for k,v in test_case_dict.items():
                final_dict[k]=eval(v) #If no exception evaluate the function and add it to final_dict

        except Exception as e:
            exception_dict[k]=e #extract exception
            test_case_dict.pop(k)
            try_except_avoider(test_case_dict) #recursive function to handle remaining functions

        finally:  #cleanup
            final_dict.update(exception_dict)
            return final_dict #combine exception dict and  final dict

    return try_except_avoider(test_case_dict) 

Code ausführen:

def add(a,b):
    return (a+b)
def sub(a,b):
    return (a-b)
def mul(a,b):
    return (a*b)

case = {"AddFunc":"add(8,8)","SubFunc":"sub(p,5)","MulFunc":"mul(9,6)"}
solution = special_func(case)

Ausgabe sieht wie folgt aus:

{'AddFunc': 16, 'MulFunc': 54, 'SubFunc': NameError("name 'p' is not defined")}

In Variablen konvertieren:

locals().update(solution)

Variablen würden folgendermaßen aussehen:

AddFunc = 16, MulFunc = 54, SubFunc = NameError("name 'p' is not defined")
0
DeWil

'continue' ist innerhalb eines 'außer' oder 'final' nur erlaubt, wenn sich der try-Block in einer Schleife befindet. 'continue' startet die next - Iteration der Schleife. 

Sie können also versuchen, Ihre zwei oder mehr Funktionen in einer Liste zusammenzufassen und eine Schleife zum Aufrufen Ihrer Funktion zu verwenden.

So was:

    funcs = [f,g]
        for func in funcs:
        try: func()
        except: continue

Für vollständige Informationen kannst du auf diesen Link gehen

0
LIU ZHIWEN