try print pass example error catch and python exception nested raise

python - print - ¿Cómo volver a plantear una excepción en bloques try/except anidados?



try except python 3 print error (4)

Sé que si quiero volver a plantear una excepción, uso simple raise sin argumentos en el bloque except respectivo. Pero dado una expresión anidada como

try: something() except SomeError as e: try: plan_B() except AlsoFailsError: raise e # I''d like to raise the SomeError as if plan_B() # didn''t raise the AlsoFailsError

¿Cómo puedo volver a subir el SomeError sin romper el rastro de la pila? raise solo sería en este caso volver a subir el AlsoFailsError más reciente. ¿O cómo podría refactorizar mi código para evitar este problema?


Puede almacenar el tipo de excepción, el valor y el rastreo en variables locales y usar la forma de raise de tres argumentos :

try: something() except SomeError: t, v, tb = sys.exc_info() try: plan_B() except AlsoFailsError: raise t, v, tb

En Python 3, el rastreo está almacenado en la excepción, por lo que raise e hará lo (en su mayoría) correcto:

try: something() except SomeError as e: try: plan_B() except AlsoFailsError: raise e

El único problema con lo anterior es que producirá un SomeError levemente engañoso que indica que SomeError produjo al manejar AlsoFailsError (debido a que raise e dentro de Except AlsoFailsError ), donde de hecho ocurrió exactamente lo contrario: manejamos AlsoFailsError al intentar recuperar de SomeError . Para deshabilitar este comportamiento y obtener un rastreo que nunca menciona AlsoFailsError , reemplace raise e con raise e from None .


Python 3.5 y sigs. adjunta la información de seguimiento al error de todos modos, por lo que ya no es necesario guardarlo por separado.

>>> def f(): ... try: ... raise SyntaxError ... except Exception as e: ... err = e ... try: ... raise AttributeError ... except Exception as e1: ... raise err from None >>> f() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 9, in f File "<stdin>", line 3, in f SyntaxError: None >>>


Según la sugerencia de Drew McGowen , pero ocupándose de un caso general (donde existe un valor de retorno s ), aquí hay una alternativa a la respuesta del usuario4815162342 :

try: s = something() except SomeError as e: def wrapped_plan_B(): try: return False, plan_B() except: return True, None failed, s = wrapped_plan_B() if failed: raise


Incluso si la solución aceptada es correcta, es bueno apuntar a la biblioteca Six que tiene una solución Python 2 + 3, utilizando six.reraise .

seis. reubicación ( exc_type , exc_value , exc_traceback = None)

Reordene una excepción, posiblemente con un traceback diferente. [...]

Entonces, puedes escribir:

import six try: something() except SomeError: t, v, tb = sys.exc_info() try: plan_B() except AlsoFailsError: six.reraise(t, v, tb)