Python 获取最后一个函数';从回溯中调用参数?
我可以得到在回溯中调用的最后一个函数的参数吗?怎么做 我想为标准错误制作一个捕获器,使代码可读,同时向用户提供详细信息 在下面的示例中,我希望GET_PARAMS返回一个提供给os.chown的参数元组。检查Alex Martelli建议的Python 获取最后一个函数';从回溯中调用参数?,python,exception-handling,traceback,Python,Exception Handling,Traceback,我可以得到在回溯中调用的最后一个函数的参数吗?怎么做 我想为标准错误制作一个捕获器,使代码可读,同时向用户提供详细信息 在下面的示例中,我希望GET_PARAMS返回一个提供给os.chown的参数元组。检查Alex Martelli建议的inspect模块,我找不到它 def catch_errors(fn): def decorator(*args, **kwargs): try: return fn(*args, **kwargs)
inspect
模块,我找不到它
def catch_errors(fn):
def decorator(*args, **kwargs):
try:
return fn(*args, **kwargs)
except (IOError, OSError):
msg = sys.exc_info()[2].tb_frame.f_locals['error_message']
quit(msg.format(SEQUENCE_OF_PARAMETERS_OF_THE_LAST_FUNCTION_CALLED)\
+ '\nError #{0[0]}: {0[1]}'.format(sys.exc_info()[1].args), 1)
return decorator
@catch_errors
def do_your_job():
error_message = 'Can\'t change folder ownership \'{0}\' (uid:{1}, gid:{2})'
os.chown('/root', 1000, 1000) # note that params aren't named vars.
if __name == '__main__' and os.getenv('USERNAME') != 'root':
do_your_job()
(感谢decorator)对于此类检查任务,始终首先考虑标准库中的模块。这里,为您提供给定帧的参数值,并为您提供来自回溯对象的感兴趣帧。使用装饰器来实现您试图实现的目标的问题是,异常处理程序获得的帧是
dou your_job()
s,而不是os.listdir()
s、os.makedirs()
s或os.chown()
s。因此,您将要打印的信息是do\u your\u job()
的参数。为了获得我认为您想要的行为,您必须装饰您正在调用的所有库函数。以下是此类函数的示例和一些您无法回避的问题:
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])
我没有使用
inspect.getinnerframes()
来显示获取所需帧的另一种方法。虽然它简化了一点,但它也做了一些您不需要的额外工作,而速度相对较慢(inspect.getinnerframes()
读取回溯中每个模块的源文件;这对于一次调试调用并不重要,但在其他情况下可能会出现问题) 您的except应该是“except(IOError,OSError):”。目前的情况是,您只捕获IOError,然后将异常实例分配给OSError。我不明白:什么是slow-inspect或您的方式?似乎只有在函数内部引发异常时,您的代码才会工作。
{'a': 1, 'c': 4, 'b': 2, 'e': {'g': 6, 'f': 5}, 'd': ()}