unboundlocalerror - ¿Puedo obtener las variables locales de una función de Python desde la que se lanzó una excepción?
unboundlocalerror local variable referenced before assignment (5)
Estoy escribiendo un sistema de registro personalizado para un proyecto. Si una función lanza una excepción, quiero registrar sus variables locales. ¿Es posible acceder a las variables locales de la función de subida desde el bloque de excepción que detectó la excepción? Por ejemplo:
def myfunction():
v1 = get_a_value()
raise Exception()
try:
myfunction()
except:
# can I access v1 from here?
En general, es un diseño más limpio para pasar el valor a la excepción, si sabe que su código de manejo de excepciones lo va a necesitar. Sin embargo, si está escribiendo un depurador o algo así, donde necesitará acceder a las variables sin saber cuáles están por adelantado, puede acceder a una variable arbitraria en el contexto donde se lanzó la excepción:
def myfunction():
v1 = get_a_value()
raise Exception()
try:
myfunction()
except:
# can I access v1 from here?
v1 = inspect.trace()[-1][0].f_locals[''v1'']
La funcionalidad de la función de trace
y el formato de los objetos de traceback
que trata, se describen en la documentación del módulo de inspect
.
Puede buscar las variables locales en el objeto de marco, que puede obtener de sys.exc_info
.
>>> import sys
>>> def f(a):
... b = a - 1
... print 1.0 / b
...
>>> try:
... f(1)
... except Exception, e:
... print sys.exc_info()[2].tb_next.tb_frame.f_locals
...
{''a'': 1, ''b'': 0}
Tendrá que incluir el número apropiado de tb_next
s dependiendo de la profundidad de la pila en la que se lanzó la excepción.
Sí, si es tu propio tipo de excepción. Me gusta esto:
>>> class MyExn(Exception):
... def __init__(self, val):
... self.val = val
... def __str__(self):
... print "something wrong with:", str(self.val)
...
>>> def foo():
... val = 42
... raise MyExn(val)
...
>>> foo()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in foo
__main__.MyExnsomething wrong with: 42
>>> # Or in a try block:
>>> try:
... foo()
... except MyExn as e:
... print e.val
...
42
>>>
def myFunction()
v1 = get_a_value()
raise Exception(v1)
try:
myFunction()
except Exception, e:
v1 = e.args[0]
try:
myfunction()
except:
import sys
type, value, tb = sys.exc_info()
while tb.tb_next:
tb = tb.tb_next
frame = tb.tb_frame
print frame.f_locals[''v1'']