Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Python Exceptions (besser) auswerten Carsten Grohmann 8. Januar 2014 Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Agenda I Kurze Einführung in Python Exceptions I Real Life I Individueller Exception-Handler I Ferdsch I Weiterführende Informationen I Nachwort Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Nischt dun Exception abgefangen und mit eigener Fehlermeldung beenden Exception abfangen und aufräumen Exceptions abfangen, aufräumen und wieder auslösen I Exceptions sind in Python das Mittel der Wahl, um mit Fehlern umgezugehen I Exceptions sollten nach Möglichkeit nahe am Entstehungsort abgefangen und behandelt werden Nicht abgefangenen Exceptions I I I werden auf der Konsole angezeigt und/oder ins Log geschrieben führen zu einem automatischen Programmabbruch I Python merkt sich nur die letzte Exception (Stichwort Exception im except: Block) I Exceptions enthalten den kompletten Stack inkl. lokaler und globaler Variablen , (im Gegensatz zu anderen Sprachen wie Java) Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 Nischt dun Exception abgefangen und mit eigener Fehlermeldung beenden Exception abfangen und aufräumen Exceptions abfangen, aufräumen und wieder auslösen # !/ usr / bin / env python2 2 3 4 5 1 2 3 4 5 i = 1 j = 0 i/j # ./ donothing . py Traceback ( most recent call last ): File " ./ donothing . py " , line 5 , in < module > i/j ZeroDivisionE rror : integer division or modulo by zero Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 Nischt dun Exception abgefangen und mit eigener Fehlermeldung beenden Exception abfangen und aufräumen Exceptions abfangen, aufräumen und wieder auslösen # !/ usr / bin / env python2 2 3 import sys 4 5 6 7 8 9 10 11 1 2 i = 1 j = 0 try : i/j except ZeroDiv isionError : print " Fehler : Division durch 0 " sys . exit (0) # ./ donothing2 . py Fehler : Division durch 0 Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 2 3 4 5 6 7 8 9 10 11 12 1 2 Nischt dun Exception abgefangen und mit eigener Fehlermeldung beenden Exception abfangen und aufräumen Exceptions abfangen, aufräumen und wieder auslösen # !/ usr / bin / env python2 f = None try : try : content = open ( ’/ etc / motd ’ ). read () foo = ’ bar ’ in content except ( IOError , OSError ): foo = ’ not found ’ finally : if f : f . close () print " Foo : % s " % foo # ./ catch . py False I Ab Py2.5 sind try:except und try:finally kombinierbar Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Nischt dun Exception abgefangen und mit eigener Fehlermeldung beenden Exception abfangen und aufräumen Exceptions abfangen, aufräumen und wieder auslösen In manchen Fehlersituationen ist es sinnvoll die Behandlung der Exception kurz auszusetzen, um zum Beispiel um vorher noch Werte zu korrigieren - Stichwort Rollback der Datenbank. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 db = sqlite3 . connect ( MyDB ) try : cursor = db . cursor () cursor . execute ( ’ CREATE TABLE cfg ( key VARCHAR (36) ’ ’ PRIMARY KEY , value TEXT NOT NULL ); ’) insert_data ( cursor ) except : db . rollback () log . error ( ’ Transaction rollback ’) raise else : log . info ( ’ Transaction commit ’) db . commit () return Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Codequalität Beispiel Lösung I Alle möglichen Exceptions sauber abgefangen und behandelt? I Was tun, wenn es doch passiert? I Bekommt der Administrator / Entwickler alle notwendigen Informationen, um das Problem zu lösen bzw. zu umgehen? I Wer schreibt perfekten Code? Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Codequalität Beispiel Lösung Hmm, auf einem Windows mit französischen Spracheinstellungen gab es einen UnicodeEncodeError mit dem Zeichen ’\uxe9’ (é LATIN SMALL LETTER E WITH ACUTE) an Position 88. Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Codequalität Beispiel Lösung Aber wo?! 1 try : 2 if not is_filelike : os . chdir ( os . path . dirname ( infilename )) infile = open ( infilename ) else : infile = infilename p = P r o g r e s s X ml W i dg e t Bu i l de r ( input_file = infile ) p . parse ( infile ) except ( IOError , OSError , SAXParseException ) , msg : [...] return False except Exception , msg : wx . MessageBox ( _ ( ’ An exception occurred while loading file "% s ".\ n " [...] return False 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Codequalität Beispiel Lösung Stack Trace enthält den vollständigen Inhalt des Stacks zum Zeitpunkt der Exception inklusive: I Fehlerursache und -details I Dateinamen und Zeilennummern I Funktionsnamen und -code I Lokale und globale Variablen Individueller Exception Handler schreiben um damit den kompletten Stack Trace ins Log schreiben. Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Struktur Pseudo Code Implementierung Installation Verblemberte Zeit? 1. Alle Variablen initialisieren 2. Allgemeine Details loggen 2.1 Datum und Uhrzeit 2.2 Versionsnummern der Anwendung, des Python-Interpreters und wichtiger Bibliotheken 2.3 Art der Exception 2.4 Nachricht der Exception 3. Liste der Frames aus dem Stack Trace extrahiert (inspect.getinnerframes()) 4. Für jeden Frame: 4.1 Kontext aus dem Quelltext loggen 4.2 Lokale Variablen des Frames loggen 5. Immer alle Variablen löschen, um Zirkelbezug zu vermeiden Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 2 3 4 5 6 7 8 9 10 11 12 13 Struktur Pseudo Code Implementierung Installation Verblemberte Zeit? def my_exception ( exc_type , exc_value , exc_tb ): < Alle Variablen initialisieren > try : try : < Allgemeine Details loggen > < Liste der Frames ermitteln > for frame_details in stack_list : < Kontext loggen > < Lokale Variablen des Frames loggen > except Exception , e : < Aktuelle Exceptions behandeln > finally : < Alle Variablen loeschen > Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Struktur Pseudo Code Implementierung Installation Verblemberte Zeit? Vollständige Quelltext (MIT-Lizenz) in einer erweiterten Form: https://bitbucket.org/agriggio/wxglade/src/tip/log.py Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Struktur Pseudo Code Implementierung Installation Verblemberte Zeit? 1. Logging initialisieren 2. Exception Handler registrieren 1 sys . excepthook = my_exception Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Struktur Pseudo Code Implementierung Installation Verblemberte Zeit? Integration in das Python-Logging ist einfach ,: 1 2 3 4 5 I Eigene Klasse von logging.Formatter ableiten und formatException() entsprechend der vorangegangenen Ausführung mit Leben füllen. I Einfache Funktion für den Exception Hook schreiben def my_hook ( exc_type , exc_value , exc_tb ): logging . error ( _ ( " An unhandled exception occurred " ) , exc_info =( exc_type , exc_value , exc_tb ) ) Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende I 1 2 3 4 5 6 7 2 Logging mit eigenen Formatter initialisieren default_forma tter = myFormatter ( ’ %( levelname ) -8 s : %( message ) s ’) logger = logging . getLogger () console = logging . StreamHandler () console . setLevel ( logging . INFO ) console . setFormatter ( default_formatter ) logger . addHandler ( console ) I 1 Struktur Pseudo Code Implementierung Installation Verblemberte Zeit? Eigenen Exception Handler aktivieren import sys sys . excepthook = my_hook Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Mehr Details Vorher vs. Nacher Ab jetzt gibt es Details von: 1 2 3 I nicht abgefangene Exceptions via my_hook() I abgefangenen Exceptions über den Aufruf von logging.exception() # ./ donothing3 . py ERROR : An unhandled exception occurred An unexpected error occurred ! 4 5 6 Date and time : Python version : 2014 -01 -05 T17 :42:43.074278 2.7.6 7 8 9 Exception type : < type ’ exceptions . ZeroDivisionError ’ > Exception details : integer division or modulo by zero Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 2 3 4 5 6 Mehr Details Vorher vs. Nacher Application stack trace : Stack frame at level 0 == == === = = = = = = = = = = === == File " ./ donothing3 . py " , line 8 Function " < module >() " Source code context : 7 import log log . init () 8 9 10 11 12 13 -> i = 1 j = 0 i/j Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 2 3 4 5 6 7 8 9 Mehr Details Vorher vs. Nacher Local variables : -> i ( < type ’ int ’ >): 1 -> j ( < type ’ int ’ >): 0 -> log ( < type ’ module ’ >): < module ’ log ’ from ’/ home / carste -> __builtins__ ( < type ’ module ’ >): < module ’ __builtin__ ’ ( -> __file__ ( < type ’ str ’ >): ’ ./ donothing3 . py ’ -> __package__ ( < type ’ NoneType ’ >): None -> __name__ ( < type ’ str ’ >): ’ __main__ ’ -> __doc__ ( < type ’ NoneType ’ >): None Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende 1 2 3 4 Mehr Details Vorher vs. Nacher Traceback ( most recent call last ): File " ./ donothing . py " , line 5 , in < module > i/j ZeroDivisionE rror : integer division or modulo by zero vs. 1 2 3 4 5 6 i = 1 j = 0 -> i / j Local variables : -> i ( < type ’ int ’ >): 1 -> j ( < type ’ int ’ >): 0 Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende I The Python Tutorial - Errors and Exceptions http://docs.python.org/2/tutorial/errors.html I Python Dokumentation des Modules „logging“ http://docs.python.org/2/library/logging.html I Python Dokumentation des Modules „inspect“ http://docs.python.org/2/library/inspect.html I Doug Hellmann - Python Exception Handling Techniques http://doughellmann.com/2009/06/python-exception-handling-techniques.html Carsten Grohmann Python Exceptions (besser) auswerten Agenda Kurze Einführung Python Exceptions Real Life Individueller Exception-Handler Ferdsch Weiterführende Informationen Ende Setzt den Exception Handler überall ein - die Lizenz erlaubt es! Carsten Grohmann Python Exceptions (besser) auswerten