2013-07-03 61 views
3

我正在用Python 2編寫一個應用程序。我想要有一個全球異常處理程序,它可以捕獲應用程序中的任何和所有未捕獲的異常 - 在子線程中的主線程(程序使用線程) - 並生成一個很好的報告,用戶可以向我發送電子郵件,其中包括異常堆棧跟蹤,文件,行號等,還包括幾個本地和全局變量的值。Python 2:在異常期間獲取信息的最佳方式是什麼?

主線程異常當然會終止程序。子線程異常顯然不會殺死應用程序,這很好(而且是我期望的)。但無論是哪種情況,我都希望以一種清晰的方式向用戶報告這些異常情況,以便他們提醒我所有必要的信息。

我在想這樣做的最好方法是重寫sys.excepthook,因爲我看到的唯一的其他選擇是將每個函數都封裝在一個巨大的try/except塊中,而且我甚至不確定if這些可以嵌套(說實話,我沒有嘗試過),所以當我有辦法處理預期的異常時,我可以優雅地做。

這裏基本上是我希望能夠做到:

  1. 產生堆棧跟蹤,包括在現有的文件名和行號,只是當它打印之前退出異常的Python會做(或線程終止時)
  2. 此外,檢索本地範圍(即發生異常的函數)以及所有全局變量中的所有變量(這可以用globals()方便地完成)我也可以想要一些其他特定的變量 - 例如,我傾向於將我的應用程序變成類,所以我可以簡單地實例化它們,然後再加上類可以保存所有應用程序範圍的變量,所以我會wa nt這些應用程序範圍的變量,即使異常可能發生在這個主要應用程序類下面的某個類中。
  3. 將所有這些轉換爲一個格式化的文本字符串,在一個變量中(我可以自己做,只需要訪問信息),然後對它做些什麼 - 將它轉儲到磁盤上的文件,發送它通過電子郵件,通過UDP發送到一個自定義的服務器,把它放在一個對話框中,以便用戶可以複製/粘貼它,無論如何。目標只是讓它以文本字符串形式出現。

我已經對sys.excepthook做了一點實驗,但是我有點頭腦不清,因爲我不確定如何從異常中真正提取所有這些信息。我已經讀了一些關於traceback模塊的內容,但它對我來說並沒有多大意義 - 它看起來像指向追溯「對象」,但被饋入到excepthook方法中的追溯對象沒有任何屬性或屬性列在文檔中,所以它顯然是不同形式的「追溯對象」。

一些建議或指向正確的文件方向將不勝感激!

+0

+1大格格,很好的問題,表現爲思想和人性化。與我看到的一些問題形成鮮明對比。 –

+0

同意Alex G.和我對答案非常感興趣 –

回答

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,不要期望它具有跟蹤模塊中列出的任何方法。這裏有一個回溯對象的屬性:

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

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()   
相關問題