2009-08-05 7 views
6

Normalerweise nicht gehandhabte Ausnahmen gehen zum stdout (oder stderr?), Ich baue eine App, wo ich diese Informationen an die GUI übergeben möchte, bevor heruntergefahren und es dem Benutzer angezeigt wird, und gleichzeitig möchte ich es schreiben in eine Protokolldatei. Also, ich brauche eine str mit dem vollständigen Text der Ausnahme.Python: Wie kann ich mit einer unbehandelten Ausnahme umgehen?

Wie kann ich das tun?

Antwort

0
try: 
    # blah blah The Main Loop, function, whatever... 
except e: 
    do_something_with(str(e)) 
+4

Ich denke, du meinst „außer Ausnahme, e:“ ... –

2
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 
15

sys.excepthook Verwenden der Basisausnahmebehandler zu ersetzen. Sie können, wie etwas tun:

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 

Dies trifft auf alle nicht behandelten Ausnahmen, so dass Sie nicht ... außer Block auf der obersten Ebene des Codes einen Versuch benötigen.

+2

Es speichert alle nicht behandelten Ausnahmen im Hauptthread, aber wenn Sie das Threading-Modul verwenden, threading.Thread hat seinen eigenen try/except Handler die umgeht sys.excepthook. Siehe http://bugs.python.org/issue1230540. – metamatt

9

Sie haben bereits ausgezeichnete Antworten erhalten, ich wollte nur noch einen Tipp hinzufügen, der mir über die Jahre hinweg in verschiedenen Sprachen für das spezifische Problem "sauber diagnostizieren, loggen usw. out of memory Fehler?" Das Problem ist, wenn der Code die Kontrolle bekommt, bevor genug Objekte zerstört wurden und ihr Speicher recycelt wurde, könnte der Speicher zu eng sein, um die Protokollierung von Eigenschaften, GUI-Arbeit, usw. durchzuführen - wie stellen wir sicher, dass dies nicht geschieht?

Antwort: ein Notfall-Vorrat bauen, so dass Sie wissen, dass Sie es in solchen Notfällen verbringen:

rainydayfund = [[] for x in xrange(16*1024)] # or however much you need 

def handle_exception(e): 
    global rainydayfund 
    del rainydayfund 
    ... etc, etc ... 
0

Ich versuchte Neil's answer verwenden, aber es mit einer Tkinter GUI funktioniert nicht. Dafür musste ich 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() 
Verwandte Themen