2009-10-30 63 views
1

我可以获取在回溯中调用的最后一个函数的参数吗?怎么样?从回溯中获取最后一个函数的调用参数?

我想制作一个标准错误捕捉器来制作可读的代码,但是却向用户提供了详细的信息。

在以下示例中,我希望GET_PARAMS向我返回提供给os.chown的参数元组。检查由Alex Martelli建议的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() 

(感谢Jim Robert用于装饰)

+2

你的除外应该是“除(IOError,OSError):”。就目前而言,您只捕获IOError,然后将异常实例分配给OSError。 – jamessan 2009-10-30 16:34:46

+0

糟糕。谢谢,詹姆斯。 – 2009-10-30 17:56:21

回答

0

与使用装饰为你想达到什么样的问题是,异常处理程序获取框架是do_your_job() S,不os.listdir() S,os.makedirs() S或os.chown()秒。所以你要打印的信息是do_your_job()的参数。为了获得我认为你打算的行为,你必须修饰你所调用的所有库函数。

5

对于这样的检验任务,总以为在标准库中第一个模块inspect的。这里,inspect.getargvalues给出了给定帧的参数值,inspect.getinnerframes给出了来自回溯对象的感兴趣帧。

+0

+1马尔泰利教我另一件我不知道的事情。 – Yarin 2012-07-26 00:18:13

3

这里是和这样的功能的例子一些问题,你不能得到解决:

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()为回溯中的每个模块读取源文件;这对调试调用并不重要,但在其他情况下可能是问题)。

+0

我不明白:什么是慢 - 检查或你的方式? – 2009-10-31 11:04:51

+0

似乎只有在函数内引发异常时,您的代码才有效。 – 2009-10-31 11:21:12

相关问题