¿Cómo puedo capturar todas las excepciones de una aplicación wxPython?
-
03-07-2019 - |
Pregunta
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 hacer que la aplicación se bloquee?
Idealmente, me gustarí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 como esta antes, pero no he podido encontrar nada que parezca útil a través de google.
Solución
Para el registro de 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 lo 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 vuelva a elevar 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
Otros consejos
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
(consulte 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 el archivo que desee, junto con el rastreo y hacer lo que quiera con la excepción (volver a generarlo, mostrar un mensaje de error y permitir que el usuario continúe usando su aplicación, etc.).
En cuanto al inicio de sesión estándar, la mejor manera para mí era escribir algo similar al OutWrapper de DzinX.
Si está en la etapa de depuración, considere vaciar los archivos de registro después de cada entrada. Esto perjudica mucho el rendimiento, pero si logra causar un defecto en algún código C subyacente, sus registros no lo engañarán.
Hay varias maneras. Puede poner un bloque try..catch en wxApplication :: OnInit, sin embargo, eso no siempre funcionaría con Gtk.
Una buena alternativa sería anular Application :: HandleEvent en su clase derivada de 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.