web-dev-qa-db-fra.com

python catch exception et continue try block

Puis-je revenir à l'exécution de try-block après qu'une exception se soit produite? (Le but est d'écrire moins) Par exemple:

try:
    do_smth1()
except:
    pass

try:
    do_smth2()
except:
    pass

contre

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

Non ... tu ne peux pas faire ça. C'est comme ça que Python a sa syntaxe. Une fois que vous avez quitté un bloc try en raison d'une exception, vous ne pouvez plus revenir.

Qu'en est-il une for-loop cependant?

funcs = do_smth1, do_smth2

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

Notez cependant qu’il est considéré comme une mauvaise pratique d’avoir une except pure. Vous devriez plutôt rechercher une exception spécifique. J'ai capturé pour Exception parce que c'est aussi bon que je puisse faire sans savoir quelles exceptions les méthodes pourraient générer.

44
iCodez

Alors que les autres réponses et celle acceptée sont correctes et doivent être suivies dans le code réel, vous pouvez essayer le module fuckitpy ( https://github.com/ajalt/fuckitpy ).

Votre code peut être changé comme suit:

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

Ensuite, appeler myfunc() appellerait do_smth2() même s'il existe une exception dans do_smth1())

Note: S'il vous plaît faites pas essayez-le dans n'importe quel code, c'est un blasphème

19
pankaj

Vous pouvez réaliser ce que vous voulez, mais avec une syntaxe différente. Vous pouvez utiliser un bloc "finally" après le try/except. En procédant ainsi, python exécutera le bloc de code, que l'exception soit levée ou non.

Comme ça:

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

Mais si vous voulez exécuter do_smth2 () uniquement si l'exception n'a pas été levée, utilisez un bloc "else":

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

Vous pouvez aussi les mélanger, dans une clause try/except/else/finally . Amusez-vous!

6
Lucas Ribeiro

Vous pourriez parcourir vos méthodes ...

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

une façon dont vous pouvez gérer c'est avec un générateur. Au lieu d'appeler la fonction, cédez-la; alors ce qui consomme le générateur peut envoyer le résultat du rappel dans le générateur, ou une sentinelle si le générateur échoue: Le trampoline qui accomplit ce qui précède peut ressembler à ceci:

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

un générateur compatible serait le suivant:

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

Notez que do_many_things() fait pas appelle do_smth*, il les produit simplement, et consume_exceptions les appelle en son nom

Je ne pense pas que tu veuilles faire ça. La manière correcte d'utiliser une instruction try en général est aussi précise que possible. Je pense qu'il vaudrait mieux faire:

try:
    do_smth1()
except Stmnh1Exception:
    # handle Stmnh1Exception

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

Selon où et à quelle fréquence vous devez le faire, vous pouvez également écrire une fonction qui le fait pour vous:

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

live_dangerously(do_smth1)
live_dangerously(do_smth2)

Mais comme d'autres réponses l'ont noté, le fait d'avoir un except null est généralement le signe que quelque chose d'autre ne va pas avec votre code.

1
Dan

special_func pour éviter la répétition try-except:

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 d'exécution:

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)

La sortie ressemble à:

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

Pour convertir en variables:

locals().update(solution)

Les variables ressembleraient à:

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

'continue' est autorisé dans un 'excepté' ou 'enfin' seulement si le bloc try est dans une boucle. 'continue' provoquera le début de l'itération next de la boucle. 

Vous pouvez donc essayer de mettre vos deux ou plusieurs fonctions dans une liste et utiliser boucle pour appeler votre fonction.

Comme ça:

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

Pour une information complète, vous pouvez aller à ce lien

0
LIU ZHIWEN