3

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

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

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

这基本上是我想做的事情:

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

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

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

4

2 回答 2

1

输入到 excepthook 方法的回溯对象没有文档中列出的任何属性或属性,因此它显然是“回溯对象”的不同形式。

我没有看到:

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() 函数中,如果将参数命名为 variable traceback,不要期望它具有 traceback 模块中列出的任何方法。以下是回溯对象的属性:

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

于 2013-07-03T07:45:17.703 回答
0
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

Example Output:

>>> 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()          
于 2013-07-03T08:57:27.007 回答