Python 2:在异常期间获取信息的最佳方法是什么?

时间:2013-07-03 07:22:28

标签: python exception

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

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

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

这基本上是我希望能够做到的:

  1. 生成堆栈跟踪,包括可用的文件名和行号,就像Python在退出之前(或线程终止时)打印异常一样;
  2. 此外,检索本地范围内的所有变量(即发生异常的函数)以及所有全局变量(这可以通过globals()轻松完成)我可能还需要一些其他特定变量 - 例如,我倾向于将我的应用程序变成类,所以我可以简单地实例化它们,然后加上类可以保存所有应用程序范围的变量,所以我想要那些应用程序范围的变量,即使异常可能在内部发生这个主应用程序类下面的一些类。
  3. 将所有这些转换为格式化的文本字符串,在变量中(我可以自己做,只需要访问信息),然后用它做一些事情 - 将它转储到磁盘上的文件中,发送它通过电子邮件,通过UDP将其发送到自定义服务器,在对话框中将其抛出,以便用户可以复制/粘贴它,无论如何。目标只是让它以文本字符串形式出现。
  4. 我已经对sys.excepthook进行了一些实验,但我有点过头了,因为我不知道如何从异常中提取所有这些信息。我已经阅读了一些关于回溯模块的内容,但老实说对我来说没有多大意义 - 它看起来像是指追溯“对象”,但是追溯到excepthook方法的追溯对象没有任何属性或属性在文档中列出,所以它显然是一种不同形式的“追溯对象”。

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

2 个答案:

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

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

答案 1 :(得分: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

示例输出:

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