Estoy confundido sobre el manejo de excepciones en python3. Digamos que quiero capturar una excepción y almacenarla para su uso posterior; ¿Por qué no funciona el siguiente código? (eleva un NameError: name 'e' is not defined)

try:
    [][0]
except IndexError as e:
    pass
e

¿Por qué e se trata como una variable local dentro del bloque try? Como una forma de evitarlo, me di cuenta de que podía "reasignarlo"; a saber, el siguiente código funciona:

try:
    [][0]
except IndexError as e:
    z = e
z

Pero entonces, ¿por qué lo siguiente todavía no funciona?

try:
    [][0]
except IndexError as e:
    e = e
e

El código anterior aún genera un NameError: name 'e' is not defined; pero ¿e = e no debería comportarse exactamente igual que z = e?

Por otra parte, encontré una solución para usar la excepción como quiero, pero agradecería su ayuda para comprender por qué los otros dos intentos fallan. Gracias de antemano.

1
AndreasT 25 jun. 2020 a las 23:05

2 respuestas

La mejor respuesta

Una forma menos ambigua de manejar los errores en la forma en que tiene la intención sería como tal:

error = None
try:
    [][0]
except IndexError as e:
    error = e
if error:
    pass # handle error here

O

errors = []
try:
    [][0]
except IndexError as e:
    errors.append(e)
if errors:
    pass # handle error(s) here

Siempre he encontrado que el alcance local de Python es un poco confuso y preocupante porque las cosas que suceden dentro de un alcance son accesibles después de su alcance.

La razón por la cual z es accesible fuera del alcance y no lo es, es porque e se limpia adecuadamente después de que se sale del alcance. Donde como z parece haber quedado atrás. Pero mis ejemplos muestran una forma más explícita de mostrar lo que realmente está sucediendo (sin ambigüedad). En su tercer ejemplo, la razón por la que e todavía no existe es porque todavía está programado para ser limpiado después del alcance, aunque el valor haya cambiado, la referencia original no.

1
gabeio 25 jun. 2020 a las 21:42

No funciona como z porque e ya está definido aquí except IndexError as e:. Lo haces igual a sí mismo y luego, después del bloqueo catch, desaparece porque ya no está en el alcance.

Cuando asignó z es una nueva variable, no se borrará después de ese bloque.

2
Kamil Poniewierski 25 jun. 2020 a las 21:10