Hook per modificare il comportamento delle eccezioni in Python
Che bello. Ogni giorno di più penso che Python sia il linguaggio di programmazione definitivo.
Oggi mi sono trovato nella necessità di tracciare in maniera dettagliata gli errori di un'applicazione Python-PyQt sulla quale sto lavorando. L'idea di fondo era che sarebbe stato infinitamente utile mostrare una message box nella quale si informava l'utente di un malfunzionamento del software, e nel mentre tracciare l'errore in maniera dettagliata su un file, per aiutare le procedure di debug.
Follow up:
Cercando su google e documentazione Python ho scoperto dell'esistenza di sys.excepthook che altro non è che la funzione che stampa il traceback di errore. Questa funzione accetta tre parametri:
- exc_type: il tipo dell'eccezione
- exc_value: l'istanza dell'eccezione
- exc_traceback: l'istanza di "traceback"
Questi parametri vengono passati automaticamente ogni volta che un'eccezione non gestita viene lanciata.
Come qualsiasi cosa in Python, questa si può sovrascrivere con un callable custom. Vediamo un esempio:
Python:
| import sys | |
| def _excepthook(exc_type, exc_value, exc_traceback): | |
| print "Errore" | |
| sys.excepthook = _excepthook |
In questo caso, ogni volta che viene lanciata una eccezione semplicemente viene stampato il messaggio "Errore". Non è molto utile, ma è comunque un primo passo.
Passiamo adesso a vedere qualcosa di più utile:
Python:
| import sys | |
| import traceback | |
| from PyQt4.QtCore import * | |
| from PyQt4.QtGui import * | |
| def _excepthook(exc_type, exc_value, exc_traceback): | |
| message = traceback.format_exception(exc_type, exc_value, exc_traceback) | |
| QMessageBox.critical( | |
| None, | |
| "Exception occurred", | |
| message, | |
| ) | |
| sys.excepthook = _excepthook |
Finalmente qualcosa di utile! Adesso, ogni volta che viene lanciata una eccezione, apparirà una message box, che mostrerà all'utente il traceback completo dell'eccezione. Per ottenere il messaggio a partire da un 'istanza della classe "traceback" si utilizza il modulo traceback (Qua potrete trovare la documentazione). Utile soprattutto nel caso di applicazioni non lanciate da terminale.
Ma ancora non basta. All'inizio ci eravamo ripromessi di mostrare all'utente un messaggio più amichevole e salvare su un file il messaggio di errore. Procediamo quindi con:
Python:
| import sys | |
| import traceback | |
| from PyQt4.QtCore import * | |
| from PyQt4.QtGui import * | |
| def _excepthook(exc_type, exc_value, exc_traceback): | |
| file_name = "error.log" | |
| f = open(file_name, "w") | |
| message = traceback.format_exception(exc_type, exc_value, exc_traceback) | |
| f.write(message) | |
| f.close() | |
| QMessageBox.critical( | |
| None, | |
| "Exception occurred", | |
| "An exception is occurred. Please attach the %s file to the support request." %file_name, | |
| ) | |
| sys.excepthook = _excepthook |
A questo punto quando sarà lanciata un'eccezione apparirà una "simpatica" message box che informa l'utente di un errore e che spiega che per richiedere supporto è consigliato allegare il file contenente il traceback alla mail.
Ovviamente questo esempio è molto semplice. Si possono anche fare cose molto più complesse, tipo fare in modo che al lancio di un'eccezione non gestita l'applicazione invii direttamente una mail con il traceback e ulteriori informazioni allo sviluppatore, o fare in modo che l'applicazione termini immediatamente.
A questo punto basta includere questo codice prima del main e... Magicamente tutto funziona.
Ovviamente il codice in queste pagine è liberamente utilizzabile da chiunque, per farne quello che vuole, nei limiti della licenza di Qt e PyQt.
Deprecated: Assigning the return value of new by reference is deprecated in /home/mhd-01/www.kojia.net/htdocs/uranio/skins/_item_feedback.inc.php on line 156
Trackback address for this post
Trackback URL (right click and copy shortcut/link location)
No feedback yet
Deprecated: Assigning the return value of new by reference is deprecated in /home/mhd-01/www.kojia.net/htdocs/uranio/skins/_item_comment_form.inc.php on line 71
Deprecated: Assigning the return value of new by reference is deprecated in /home/mhd-01/www.kojia.net/htdocs/uranio/skins/_item_comment_form.inc.php on line 115
Comments are not allowed from anonymous visitors.