En error reanudar siguiente en Python

Fragmento 1

do_magic() # Throws exception, doesn't execute do_foo and do_bar do_foo() do_bar() 

Fragmento 2

 try: do_magic() # Doesn't throw exception, doesn't execute do_foo and do_bar do_foo() do_bar() except: pass 

Fragmento 3

 try: do_magic(); except: pass try: do_foo() ; except: pass try: do_bar() ; except: pass 

¿Hay una manera de escribir código de código 3 con elegancia?

  • Si do_magic() falla o no, do_foo() y do_bar() deben ejecutarse.
  • Si do_foo() falla o no, do_bar() debe ejecutarse.

En Basic / Visual Basic / VBS, hay una statement llamada On Error Resume Next que hace esto.

En Python 3.4 en adelante, puedes usar contextlib.suppress :

 from contextlib import suppress with suppress(Exception): # or, better, a more specific error (or errors) do_magic() with suppress(Exception): do_foo() with suppress(Exception): do_bar() 

Alternativamente, fuckit .

Si las tres funciones aceptan el mismo número de parámetros:

 for f in (do_magic, do_foo, do_bar): try: f() except: pass 

De lo contrario, envuelva la llamada de función con lambda .

 for f in (do_magic, lambda: do_foo(arg1, arg2)): try: f() except: pass 

Si usted es el que codifica las funciones, ¿por qué no progtwigr las funciones para devolver códigos de estado? Entonces serán atómicos y no tendrás que capturar el error en la sección principal. También podrá realizar retrotracción o encoding alternativa en caso de fallo.

 def do_magic(): try: #do something here return 1 except: return 0 

en el progtwig principal ..

 if do_magic() = 0: #do something useful or not... if do_foo() = 0: #do something useful or not... if do_bar() = 0: #do something useful or not... 

Un montón de ident, pero funciona.

 try: do_magic() finally: try: do_foo() finally: try: do_bar() finally: pass 

Puedes probar un bucle de “nested”, aunque no sea tan elegantemente python como quieras. La solución ´lambda´ también es una buena forma de proceder, no mencionada porque se hizo en la respuesta anterior.

editar:

 try: do_magic() finally: try: do_foo() finally: try: do_bar() except: pass 

edición 2:

Bueno, maldita sea, esta respuesta acaba de publicarse segundos antes: |

En la pregunta, Snippet 3 no funciona pero funcionará si no te importa dividir cada línea en dos líneas …

 try: do_magic() except: pass try: do_foo() except: pass try: do_bar() except: pass 

Un ejemplo de trabajo.

 import sys a1 = "No_Arg1" a2 = "No_Arg2" a3 = "No_Arg3" try: a1 = sys.argv[1] except: pass try: a2 = sys.argv[2] except: pass try: a3 = sys.argv[3] except: pass print a1, a2, a3 

… si guarda esto en test.py y luego, en un indicador de CMD en Windows, simplemente escriba test.py , devolverá No_Arg1 No_Arg2 No_Arg3 porque no hubo argumentos. Sin embargo, si proporciona algunos argumentos, si escribe test.py 111 222 devolverá 111 222 No_Arg3 etc. (Probado – Windows 7, python2.7).

En mi humilde opinión esto es mucho más elegante que las respuestas del ejemplo de anidación. También funciona exactamente como On Error Resume Next y lo uso al traducir desde VB6. Un problema es que las líneas de try no pueden contener un condicional. He encontrado que, como regla general, Python no puede contener más de uno : en una línea. Dicho esto, simplemente significa dividir la statement en 3 líneas, etc.

Si no hay parámetros …

 funcs = do_magic, do_foo, do_bar for func in funcs: try: func() except: continue