Могу ли я получить локальные переменные функции Python, из которых было создано исключение?
Я пишу пользовательскую систему ведения журнала для проекта. Если функция генерирует исключение, я хочу записать ее локальные переменные. Возможно ли получить доступ к локальным переменным функции повышения из исключающего блока, который поймал исключение? Например:
def myfunction():
v1 = get_a_value()
raise Exception()
try:
myfunction()
except:
# can I access v1 from here?
Ответы
Ответ 1
Как правило, более чистый дизайн передает значение в исключение, если вы знаете, что вам понадобится код обработки исключений. Однако, если вы пишете отладчик или что-то в этом роде, где вам нужно будет обращаться к переменным, не зная, какие из них они заранее, вы можете получить доступ к произвольной переменной в контексте, в котором было выбрано исключение:
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']
Функциональность функции trace
и формат объектов traceback
, с которыми она имеет дело, описаны в документации inspect
.
Ответ 2
def myFunction()
v1 = get_a_value()
raise Exception(v1)
try:
myFunction()
except Exception, e:
v1 = e.args[0]
Ответ 3
Вы можете искать локальные переменные в объекте фрейма, которые вы можете получить из 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}
Вам нужно будет указать соответствующее количество tb_next
в зависимости от того, насколько глубоко в стеке было выбрано исключение.
Ответ 4
Да, если это ваш собственный тип исключения. Вот так:
>>> 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
>>>
Ответ 5
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']