He tenido que resolver este problema un par de veces y me encontré con esta pregunta después de una búsqueda de lo que otras personas han hecho.
Una opción, que requerirá refactorizar un poco las cosas, sería throw
la excepción en el generador (a otro generador de manejo de errores) en lugar de raise
. Esto es lo que podría parecer:
def read(handler):
# the handler argument fixes errors/problems separately
while something():
try:
yield something_else()
except Exception as e:
handler.throw(e)
handler.close()
def err_handler():
# a generator for processing errors
while True:
try:
yield
except Exception1:
handle_exc1()
except Exception2:
handle_exc2()
except Exception3:
handle_exc3()
except Exception:
raise
def process():
handler = err_handler()
for item in read(handler):
do stuff
No siempre será la mejor solución, pero sin duda es una opción.
EDIT:
Se podría hacer todo sólo un poco más agradable con un decorador de esta manera (no he probado esto, pero debe trabajar, EDIT: no trabajar; lo arreglaré más tarde, pero el la idea es buena):
def handled(handler):
"""
A decorator that applies error handling to a generator.
The handler argument received errors to be handled.
Example usage:
@handled(err_handler())
def gen_function():
yield the_things()
"""
def handled_inner(gen_f):
def wrapper(*args, **kwargs):
g = gen_f(*args, **kwargs)
while True:
try:
yield from g
except Exception as e:
handler.throw(e)
return wrapper
return handled_inner
@handled(err_handler())
def read():
while something():
yield something_else()
def process():
for item in read():
do stuff
¡Gracias! Este parece ser el caso. ¿Podría echar un vistazo a la pregunta de seguimiento: http://stackoverflow.com/q/11366892/989121? – georg