通常情況下,未處理的異常轉到stdout(或stderr?),我正在構建一個應用程序,我想在將這些信息傳遞給GUI之前關閉並顯示給用戶,同時我想寫它到一個日誌文件。所以,我需要一個帶有例外全文的str。Python:我如何以另一種方式處理任何未處理的異常?
我該怎麼做?
通常情況下,未處理的異常轉到stdout(或stderr?),我正在構建一個應用程序,我想在將這些信息傳遞給GUI之前關閉並顯示給用戶,同時我想寫它到一個日誌文件。所以,我需要一個帶有例外全文的str。Python:我如何以另一種方式處理任何未處理的異常?
我該怎麼做?
try:
# blah blah The Main Loop, function, whatever...
except e:
do_something_with(str(e))
import sys, logging
logging.basicConfig(filename='/path/to/log/file', filemode='w')
...
try:
your_code_here()
except:
logging.exception("My code failed") # logs exception to file
# you define display_exception_in_ui as "def display_exception_in_ui(exc, tb):"
display_exception_in_ui(*sys.exc_info()[1:]) # passes exception instance, traceback
使用sys.excepthook更換基本異常處理程序。你可以這樣做:
import sys
from PyQt4 import QtGui
import os.path
import traceback
def handle_exception(exc_type, exc_value, exc_traceback):
""" handle all exceptions """
## KeyboardInterrupt is a special case.
## We don't raise the error dialog when it occurs.
if issubclass(exc_type, KeyboardInterrupt):
if QtGui.qApp:
QtGui.qApp.quit()
return
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
QtGui.QMessageBox.critical(None,"Error",
"<html>A critical error has occured.<br/> "
+ "<b>%s</b><br/><br/>" % error
+ "It occurred at <b>line %d</b> of file <b>%s</b>.<br/>" % (line, filename)
+ "</html>")
print "Closed due to an error. This is the full error report:"
print
print "".join(traceback.format_exception(exc_type, exc_value, exc_traceback))
sys.exit(1)
# install handler for exceptions
sys.excepthook = handle_exception
這捕獲所有未處理的異常,所以你並不需要在你的代碼的頂層一個try ... except塊。
它緩存在主線程所有未處理的異常,但如果你使用線程模塊,threading.Thread都有自己的try /除了處理這繞開sys.excepthook。請參閱http://bugs.python.org/issue1230540。 – metamatt 2013-07-05 07:06:22
您已經得到了很好的答案,我只是想補充一個多年來以多種語言爲我提供的技巧,以便針對特定問題「如何幹淨地診斷,記錄日誌等,01錯誤?」。問題是,如果你的代碼在有足夠的對象被銷燬並且它們的內存被回收之前得到了控制,那麼內存可能太緊以致無法進行資產記錄,GUI工作等等 - 我們如何確保這種情況不會發生?
答:建立一個緊急藏匿處,所以你知道你可以花錢在這樣的緊急情況:
rainydayfund = [[] for x in xrange(16*1024)] # or however much you need
def handle_exception(e):
global rainydayfund
del rainydayfund
... etc, etc ...
我試着用Neil's answer,但它不具有Tkinter的GUI工作。爲此,我不得不override report_callback_exception()
。
import Tkinter as tk
import tkMessageBox
import traceback
class MyApp(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
parent.report_callback_exception = self.report_callback_exception
self.parent = parent
self.button_frame = tk.Frame(self)
self.button_frame.pack(side='top')
self.button_run = tk.Button(
self.button_frame, text="Run", command=self.run
)
self.button_run.grid(row=0, column=1, sticky='W')
def run(self):
tkMessageBox.showinfo('Info', 'The process is running.')
raise RuntimeError('Tripped.')
def report_callback_exception(self, exc_type, exc_value, exc_traceback):
message = ''.join(traceback.format_exception(exc_type,
exc_value,
exc_traceback))
tkMessageBox.showerror('Error', message)
def main():
root = tk.Tk() # parent widget
MyApp(root).pack(fill='both', expand=True)
root.mainloop() # enter Tk event loop
if __name__ == '__main__':
main()
我猜你的意思是「除例外,E:」 ...... – 2009-08-06 01:55:37