with - try except python ejemplos
El manejo genérico de excepciones en Python es el "camino correcto" (6)
A veces me encuentro en la situación en la que quiero ejecutar varios comandos secuenciales como estos:
try:
foo(a, b)
except Exception, e:
baz(e)
try:
bar(c, d)
except Exception, e:
baz(e)
...
Este mismo patrón ocurre cuando las excepciones simplemente necesitan ser ignoradas.
Esto parece redundante y la sintaxis excesiva hace que sea sorprendentemente difícil de seguir al leer el código.
En C, habría resuelto este tipo de problema fácilmente con un macro, pero desafortunadamente, esto no puede hacerse en python directo.
Pregunta: ¿Cómo puedo reducir la huella del código y aumentar la legibilidad del código al encontrar este patrón?
El mejor enfoque que he encontrado es definir una función como esta:
def handle_exception(function, reaction, *args, **kwargs):
try:
result = function(*args, **kwargs)
except Exception, e:
result = reaction(e)
return result
Pero eso simplemente no se siente ni se ve bien en la práctica:
handle_exception(foo, baz, a, b)
handle_exception(bar, baz, c, d)
En su caso específico, puede hacer esto:
try:
foo(a, b)
bar(c, d)
except Exception, e:
baz(e)
O bien, puede ver la excepción un paso arriba:
try:
foo_bar() # This function can throw at several places
except Exception, e:
baz(e)
Podría usar la declaración with
si tiene Python 2.5
from __future__ import with_statement
import contextlib
@contextlib.contextmanager
def handler():
try:
yield
except Exception, e:
baz(e)
Tu ejemplo ahora se convierte en:
with handler():
foo(a, b)
with handler():
bar(c, d)
Podrías probar algo como esto. Esto es vagamente C en forma de macro.
class TryOrBaz( object ):
def __init__( self, that ):
self.that= that
def __call__( self, *args ):
try:
return self.that( *args )
except Exception, e:
baz( e )
TryOrBaz( foo )( a, b )
TryOrBaz( bar )( c, d )
Si son comandos simples de una línea, puede envolverlos en lambda
s:
for cmd in [
(lambda: foo (a, b)),
(lambda: bar (c, d)),
]:
try:
cmd ()
except StandardError, e:
baz (e)
Podrías envolver todo en una función, así que se veía así:
ignore_errors (baz, [
(lambda: foo (a, b)),
(lambda: bar (c, d)),
])
Si esto es siempre, siempre el comportamiento que desea cuando una función en particular genera una excepción, puede usar un decorador:
def handle_exception(handler):
def decorate(func):
def call_function(*args, **kwargs):
try:
func(*args, **kwargs)
except Exception, e:
handler(e)
return call_function
return decorate
def baz(e):
print(e)
@handle_exception(baz)
def foo(a, b):
return a + b
@handle_exception(baz)
def bar(c, d):
return c.index(d)
Uso:
>>> foo(1, ''2'')
unsupported operand type(s) for +: ''int'' and ''str''
>>> bar(''steve'', ''cheese'')
substring not found