在Python中查找源异常的模块名

10 投票
5 回答
5719 浏览
提问于 2025-04-15 12:45

举个例子:

>>> try:
...    myapp.foo.doSomething()
... except Exception, e:
...    print 'Thrown from:', modname(e)

Thrown from: myapp.util.url

在上面的例子中,错误实际上是在 myapp/util/url.py 这个模块里出现的。有没有办法获取到那个模块的 __name__ 呢?

我想把这个用在 logging.getLogger 这个函数里。

5 个回答

0

Python的日志记录工具已经支持这个功能——你可以查看文档。你只需要在格式字符串中指定%(module)s。不过,这样做会告诉你异常是在哪个模块被捕获的——这不一定和异常被抛出的模块是同一个。异常的追踪信息当然会告诉你异常被抛出的确切位置。

8

你可以使用 traceback模块,配合 sys.exc_info(),来以编程的方式获取错误追踪信息:

try:
    myapp.foo.doSomething()
except Exception, e:
    exc_type, exc_value, exc_tb = sys.exc_info()
    filename, line_num, func_name, text = traceback.extract_tb(exc_tb)[-1]
    print 'Thrown from: %s' % filename
12

这个应该可以工作:

import inspect

try:
    some_bad_code()
except Exception, e:
    frm = inspect.trace()[-1]
    mod = inspect.getmodule(frm[0])
    print 'Thrown from', mod.__name__

编辑:Stephan202提到了一个特殊情况。在这种情况下,我认为我们可以默认使用文件名。

import inspect

try:
    import bad_module
except Exception, e:
    frm = inspect.trace()[-1]
    mod = inspect.getmodule(frm[0])
    modname = mod.__name__ if mod else frm[1]
    print 'Thrown from', modname

问题是,如果模块没有被加载(因为在读取那个文件的代码时抛出了异常),那么inspect.getmodule这个调用会返回None。所以,我们就使用出错的那个框架所引用的文件名。(感谢Stephan202指出这一点!)

撰写回答