【问题标题】:Python 2: what is the best way to obtain information during an exception?Python 2:在异常期间获取信息的最佳方式是什么?
【发布时间】:2013-07-03 07:22:28
【问题描述】:

我正在用 Python 2 编写一个应用程序。我想要一个 全局 异常处理程序,它可以在应用程序中捕获任何和所有未捕获的异常 - 都在主线程中 在子线程中(程序使用线程) - 并生成一个很好的报告,用户可以通过电子邮件发送给我,包括异常堆栈跟踪、文件、行号等,还有几个本地和全局的值变量。

主线程异常当然会终止程序。子线程异常显然不会杀死应用程序,这很好(并且是我所期望的)。但无论哪种情况,我都希望以一种干净的方式向用户报告这些异常,以便他们可以提醒我所有必要的信息来处理它。

我认为最好的方法是覆盖 sys.excepthook,因为我看到的唯一其他选择是将每个函数包装在一个巨大的 try/except 块中,我什至不确定这些是否可以嵌套(老实说,我没有尝试过),所以当我确实有办法处理预期的异常时,我可以优雅地这样做。

这基本上是我想要做的:

  1. 生成堆栈跟踪,包括可用的文件名和行号,就像 Python 在退出之前(或线程终止时)打印异常时所做的那样
  2. 此外,检索本地范围内的所有变量(即发生异常的函数)以及所有全局变量(这可以通过 globals() 轻松完成)我可能还需要一些其他特定变量 - 示例,我倾向于将我的应用程序变成类,所以我可以简单地实例化它们,并且类可以保存所有应用程序范围的变量,所以我想要那些应用程序范围的变量,即使异常可能发生在里面此主应用程序类下的某个类。
  3. 将所有这些信息放入一个格式化的文本字符串中,在一个变量中(我可以自己做,只需要访问信息),然后用它做一些事情 - 将它转储到磁盘上的一个文件中,发送它通过电子邮件,通过 UDP 将其发送到自定义服务器,将其放在对话框中,以便用户可以复制/粘贴它,无论如何。目标只是让它以文本字符串的形式出现。

我已经对 sys.excepthook 进行了一些试验,但我有点不知所措,因为我不确定如何从异常中实际提取所有这些信息。我已经阅读了一些关于回溯模块的信息,但老实说,它对我来说没有多大意义——它看起来像是指回溯“对象”,但是被馈送到异常钩子方法的回溯对象没有任何属性或属性在文档中列出,因此它显然是一种不同形式的“回溯对象”。

非常感谢您提供一些建议或指出正确的文档方向!

【问题讨论】:

  • +1 很好的格式,很好的问题,展示了思想和人性。这与我看到的一些问题形成了鲜明的对比。
  • 同意 Alex G.,我对答案很感兴趣

标签: python exception


【解决方案1】:

被输入到异常钩子方法的回溯对象没有 文档中列出的任何属性或属性,因此 这显然是一种不同形式的“回溯对象”。

我没看到:

import sys
import traceback

def myhandler(e_class, e_instance, tb_obj):
    print "hello**************\n"
    print e_instance
    traceback.print_tb(tb_obj)
    print

    while tb_obj:
        frame = tb_obj.tb_frame
        print 'locals --->', frame.f_locals
        print 'globals -->', frame.f_globals, "\n"

        tb_obj = tb_obj.tb_next

    print "goodbye************"

sys.excepthook = myhandler

x = 10

def do_stuff():
    y = 20

    def inner():
        z = 30
        1/0

    inner()


do_stuff()




--output:--
hello**************

integer division or modulo by zero
  File "1.py", line 32, in <module>
    do_stuff()
  File "1.py", line 30, in do_stuff
    inner()
  File "1.py", line 28, in inner
    1/0

locals ---> {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '1.py', 'traceback': <module 'traceback' from '/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/traceback.pyc'>, '__package__': None, 'sys': <module 'sys' (built-in)>, 'x': 10, '__name__': '__main__', 'do_stuff': <function do_stuff at 0x2b33f0>, '__doc__': None, 'myhandler': <function myhandler at 0x2b3430>}
globals --> {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '1.py', 'traceback': <module 'traceback' from '/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/traceback.pyc'>, '__package__': None, 'sys': <module 'sys' (built-in)>, 'x': 10, '__name__': '__main__', 'do_stuff': <function do_stuff at 0x2b33f0>, '__doc__': None, 'myhandler': <function myhandler at 0x2b3430>} 

locals ---> {'y': 20, 'inner': <function inner at 0x2b33b0>}
globals --> {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '1.py', 'traceback': <module 'traceback' from '/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/traceback.pyc'>, '__package__': None, 'sys': <module 'sys' (built-in)>, 'x': 10, '__name__': '__main__', 'do_stuff': <function do_stuff at 0x2b33f0>, '__doc__': None, 'myhandler': <function myhandler at 0x2b3430>} 

locals ---> {'z': 30}
globals --> {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '1.py', 'traceback': <module 'traceback' from '/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/traceback.pyc'>, '__package__': None, 'sys': <module 'sys' (built-in)>, 'x': 10, '__name__': '__main__', 'do_stuff': <function do_stuff at 0x2b33f0>, '__doc__': None, 'myhandler': <function myhandler at 0x2b3430>} 

goodbye************

我已经阅读了一些关于回溯模块的信息,但老实说不是 对我来说很有意义

回溯模块与回溯对象不同。两人只是碰巧同名而已。在 sys.excepthook() 函数中,如果您将参数变量命名为traceback,请不要期望它具有任何在 traceback 模块中列出的方法。以下是回溯对象的属性:

http://docs.python.org/2/reference/datamodel.html

【讨论】:

    【解决方案2】:
    def myhook(etype, value, tb):
        print "Exception Type: ", etype
        print "Exception: ", value
        while tb.tb_next:
            tb = tb.tb_next
            frame = tb.tb_frame
            co = frame.f_code
            funcname = co.co_name
            coline = frame.f_lineno
            filename = co.co_filename
            print "Exception: FuncName (%s):: File(%s):: Lineno(%s)" %(funcname, filename, coline) 
            print "Exception: Globals::\n", filter(lambda x: x[0] != '__builtins__', frame.f_globals.items())
            print "Exception: Locals::\n", frame.f_locals
            print '-' * 70  
    
    sys.excepthook = myhook
    

    示例输出:

    >>> test2.bb()
    Exception Type:  <type 'exceptions.NameError'>
    Exception:  global name 'asfsdf' is not defined
    Exception: FuncName (bb):: File(C:\Python27\test\test2.py):: Lineno(7)
    Exception: Globals::
    [('aa', <function aa at 0x024F96B0>), ('bb', <function bb at 0x024F90F0>), ('__file__', 'C:\\Python27\\test\\test2.py'), ('__package__', None), ('__na
    me__', 'test2'), ('__doc__', None)]
    Exception: Locals::
    {}
    ----------------------------------------------------------------------
    Exception: FuncName (aa):: File(C:\Python27\test\test2.py):: Lineno(4)
    Exception: Globals::
    [('aa', <function aa at 0x024F96B0>), ('bb', <function bb at 0x024F90F0>), ('__file__', 'C:\\Python27\\test\\test2.py'), ('__package__', None), ('__na
    me__', 'test2'), ('__doc__', None)]
    Exception: Locals::
    {}
    ----------------------------------------------------------------------
    >>>
    
    
    cat test2.py:
    ====================
    #!/usr/bin/env python
    
    def aa():
      print asfsdf
    
    def bb():
      aa()          
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-12-18
      • 2013-08-25
      • 2012-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-10
      相关资源
      最近更新 更多