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 tendrá que 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
.
def myFunction() v1 = get_a_value() raise Exception(v1) try: myFunction() except Exception, e: v1 = e.args[0]
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 stack 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 "", line 1, in File "", line 3, in foo __main__.MyExnsomething wrong with: 42 >>> # Or in a try block: >>> try: ... foo() ... except MyExn as e: ... print e.val ... 42 >>>
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']