¿Cómo puedo capturar todas las excepciones de una aplicación wxPython?

Estoy escribiendo una pequeña aplicación de depuración para un pequeño kit que estamos desarrollando y me gustaría extenderlo a algunos usuarios para ver si pueden provocar algún fallo. ¿Alguien sabe una manera de envolver efectivamente una aplicación wxPython para detectar todas las excepciones no controladas que podrían causar que la aplicación se bloquee?

Lo ideal sería capturar toda la salida (no solo los errores) y registrarla en un archivo. Cualquier excepción no controlada debe iniciar sesión en el archivo actual y luego permitir que la excepción se transmita como de costumbre (es decir, el proceso de registro debe ser transparente).

Estoy seguro de que alguien debe haber hecho algo en este sentido antes, pero no he podido encontrar nada que parezca útil a través de Google.

Para registrar la salida estándar, puede usar un envoltorio stdout, como este:

from __future__ import with_statement class OutWrapper(object): def __init__(self, realOutput, logFileName): self._realOutput = realOutput self._logFileName = logFileName def _log(self, text): with open(self._logFileName, 'a') as logFile: logFile.write(text) def write(self, text): self._log(text) self._realOutput.write(text) 

Luego debes inicializarlo en tu archivo principal de Python (el que ejecuta todo):

 import sys sys.stdout = OutWrapper(sys.stdout, r'c:\temp\log.txt') 

En cuanto al registro de excepciones, lo más fácil es envolver el método MainLoop de wx.App en un try..except, luego extraer la información de la excepción, guardarla de alguna manera y luego volver a subir la excepción a través de raise , por ejemplo

 try: app.MainLoop() except: exc_info = sys.exc_info() saveExcInfo(exc_info) # this method you have to write yourself raise 

Para el manejo de excepciones, asumiendo que su archivo de registro se abre como registro:

 import sys import traceback def excepthook(type, value, tb): message = 'Uncaught exception:\n' message += ''.join(traceback.format_exception(type, value, tb)) log.write(message) sys.excepthook = excepthook 

Puedes usar

sys.excepthook

(ver documentos de Python )

y asignarle algún objeto personalizado, que detectaría todas las excepciones no detectadas anteriormente en su código. Luego puede registrar cualquier mensaje en cualquier archivo que desee, junto con el rastreo y hacer lo que quiera con la excepción (vuelva a subirlo, muestre un mensaje de error y permita que el usuario continúe usando su aplicación, etc.).

En cuanto al registro de la salida estándar, la mejor manera para mí fue escribir algo similar a OutWrapper de DzinX.

Si está en la etapa de depuración, considere vaciar sus archivos de registro después de cada entrada. Esto perjudica mucho el rendimiento, pero si logra causar un fallo de seguridad en algún código C subyacente, sus registros no lo engañarán.

Hay varias formas. Puede poner un bloque try..catch en wxApplication :: OnInit, sin embargo, eso no siempre funcionaría con Gtk.

Una buena alternativa sería anular la aplicación :: HandleEvent en su clase derivada wxApplication, y escribir un código como este:

 void Application::HandleEvent(wxEvtHandler* handler, wxEventFunction func, wxEvent& event) const { try { wxAppConsole::HandleEvent(handler, func, event); } catch (const std::exception& e) { wxMessageBox(std2wx(e.what()), _("Unhandled Error"), wxOK | wxICON_ERROR, wxGetTopLevelParent(wxGetActiveWindow())); } } 

Es un ejemplo de C ++, pero seguramente puedes traducirlo a Python fácilmente.