tipos - try except anidados python
¿Cómo puedo capturar todas las excepciones de una aplicación wxPython? (4)
Estoy escribiendo una pequeña aplicación de depuración para un kit que estamos desarrollando y me gustaría extenderlo a algunos usuarios para ver si pueden provocar un bloqueo. ¿Alguien sabe cómo envolver efectivamente una aplicación wxPython para detectar todas y cada una de las excepciones no controladas que causarían la falla de la aplicación?
Idealmente, me gustaría capturar todos los resultados (no solo los errores) y registrarlo en un archivo. Todas las excepciones no controladas deben registrarse en el archivo actual y luego permitir que la excepción se transmita como siempre (es decir, el proceso de registro debe ser transparente).
Estoy seguro de que alguien debe haber hecho algo así antes, pero no he logrado encontrar nada que se vea útil a través de Google.
Puedes usar
sys.excepthook
(ver los documentos de Python )
y asignarle un objeto personalizado, que atrapará todas las excepciones no detectadas anteriormente en su código. A continuación, puede registrar cualquier mensaje en cualquier archivo que desee, junto con el rastreo y hacer lo que quiera con la excepción (resérvelo, muestre un mensaje de error y permita que el usuario continúe usando su aplicación, etc.).
En cuanto a log stdout, la mejor manera para mí fue escribir algo similar a OutWrapper de DzinX.
Si se encuentra en la etapa de depuración, considere vaciar sus archivos de registro después de cada entrada. Esto perjudica mucho el rendimiento, pero si logras causar segfault en algún código C subyacente, tus registros no te inducirán a error.
Hay varias formas. Sin embargo, puede poner un bloque try..catch en wxApplication :: OnInit, que no siempre funcionaría con Gtk.
Una buena alternativa sería anular Application :: 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 se puede traducir fácilmente a Python.
Para la salida estándar de registro, puede usar un contenedor 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 debe inicializarlo en su archivo principal de Python (el que ejecuta todo):
import sys
sys.stdout = OutWrapper(sys.stdout, r''c:/temp/log.txt'')
En cuanto a las excepciones de registro, lo más fácil es ajustar el método MainLoop
de wx.App en un try ... excepto, luego extraer la información de excepción, guardarla de alguna manera y luego volver a subir la excepción mediante 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, suponiendo que su archivo de registro se abre como un 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