Вот пример такой функции и некоторые проблемы, которые вы не можете обойти:
import sys
def get_params(tb):
while tb.tb_next:
tb = tb.tb_next
frame = tb.tb_frame
code = frame.f_code
argcount = code.co_argcount
if code.co_flags & 4: # *args
argcount += 1
if code.co_flags & 8: # **kwargs
argcount += 1
names = code.co_varnames[:argcount]
params = {}
for name in names:
params[name] = frame.f_locals.get(name, '<deleted>')
return params
def f(a, b=2, c=3, *d, **e):
del c
c = 4
e['g'] = 6
assert False
try:
f(1, f=5)
except:
print get_params(sys.exc_info()[2])
Вывод:
{'a': 1, 'c': 4, 'b': 2, 'e': {'g': 6, 'f': 5}, 'd': ()}
Я не использовал inspect.getinnerframes()
, чтобы показать другой способ получить нужный кадр. Хотя он немного упрощается, он также выполняет некоторую дополнительную работу, которая вам не нужна, будучи относительно медленной (inspect.getinnerframes()
читает исходный файл для каждого модуля при трассировке; это не важно для одного вызова отладки, но может быть проблемой в другие случаи).