【问题标题】:Find module name of the originating exception in Python在 Python 中查找原始异常的模块名称
【发布时间】:2010-11-08 21:32:53
【问题描述】:

例子:

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

Thrown from: myapp.util.url

在上面的例子中,异常实际上是在 myapp/util/url.py 模块中抛出的。有没有办法获得该模块的__name__

我的意图是在logging.getLogger 函数中使用它。

【问题讨论】:

    标签: python exception logging stack-trace introspection


    【解决方案1】:

    这应该可行:

    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!)

    【讨论】:

    • 确实有效。请注意,有一个极端情况会失败,显然(刚刚尝试过):如果 some_bad_code() 是一个导入语句,它会立即导致异常(因为所述模块中的某些代码)。
    • 好点,Stephan202。我做了一个编辑,希望能充分解决这个问题。
    • @ars 我最近一直在实现类似的东西。我认为默认为文件名是不够的——我还查看了 sys.path ,如果文件名是其中一个条目的子项,我将其设为相对的。有时这会失败,因为不是每个导入都来自 sys.path,但如果成功,我可以删除扩展名并替换('\\', '/').replace('/', '.') 和大多数可能会得到缺少的模块名称。
    【解决方案2】:

    您可以使用traceback modulesys.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
    

    【讨论】:

    • 文件名与__name__不同
    • filename + linenumber 对我更有用,所以我很欣赏这个问题的答案:)
    【解决方案3】:

    这应该可以解决问题:

    import inspect
    def modname():
        t=inspect.trace()
        if t:
            return t[-1][1]
    

    【讨论】:

    • 返回定义了异常的模块,不是吗?
    • @Stephan202: 对不起,误解了问题,上面的函数会给你引发错误的模块的名称
    • 返回模块名称(url),但不返回其__name__的值(myapp.util.url
    【解决方案4】:

    Python 的日志记录包已经支持这个 - 检查documentation。您只需在格式字符串中指定%(module)s。但是,这会为您提供捕获异常的模块 - 不一定与引发的模块相同。当然,回溯会为您提供引发异常的准确位置。

    【讨论】:

    • 我想在logging.getLogger 参数中使用__name__,而不是在记录器输出中。
    • 让我们退后一步。为什么在记录器名称中包含它如此重要?您可以找到引发异常的确切文件和行号,这似乎是最重要的。
    【解决方案5】:

    我在公司博客“Python stack trace saga”上有一个关于 CrashKit 如何从 Python 堆栈跟踪计算类名和包名的故事。包括工作代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      • 1970-01-01
      • 1970-01-01
      • 2016-02-11
      • 1970-01-01
      相关资源
      最近更新 更多