Estoy usando un módulo en mi aplicación python que escribe muchos mensajes utilizando el módulo de registro. Inicialmente, estaba usando esto en una aplicación de consola y era bastante fácil obtener la salida de registro para mostrar en la consola usando un controlador de consola. Ahora he desarrollado una versión de GUI de mi aplicación usando wxPython y me gustaría mostrar todo el resultado de registro a un control personalizado - un textCtrl multilínea. ¿Existe alguna manera de que pueda crear un controlador de registro personalizado para que pueda redirigir todo el resultado de registro allí y mostrar los mensajes de registro donde sea/como yo quiera, en este caso, una aplicación wxPython.¿Cómo puedo redireccionar el registrador a wxPython textCtrl usando un controlador de registro personalizado?
Respuesta
Crear Handler
import wx
import wx.lib.newevent
import logging
# create event type
wxLogEvent, EVT_WX_LOG_EVENT = wx.lib.newevent.NewEvent()
class wxLogHandler(logging.Handler):
"""
A handler class which sends log strings to a wx object
"""
def __init__(self, wxDest=None):
"""
Initialize the handler
@param wxDest: the destination object to post the event to
@type wxDest: wx.Window
"""
logging.Handler.__init__(self)
self.wxDest = wxDest
self.level = logging.DEBUG
def flush(self):
"""
does nothing for this handler
"""
def emit(self, record):
"""
Emit a record.
"""
try:
msg = self.format(record)
evt = wxLogEvent(message=msg,levelname=record.levelname)
wx.PostEvent(self.wxDest,evt)
except (KeyboardInterrupt, SystemExit):
raise
except:
self.handleError(record)
Luego, en el control de
self.Bind(EVT_WX_LOG_EVENT, self.onLogEvent)
def onLogEvent(self,event):
'''
Add event.message to text window
'''
msg = event.message.strip("\r")+"\n"
self.logwindow.AppendText(msg) # or whatevery
event.Skip()
Tendrá que crear un logging.Handler
personalizado y agregarlo a su logging.Logger
.
De la documentación:
Handler
objetos son responsables de el envío de los mensajes de registro apropiado (en base a la gravedad los mensajes de registro) a se especifica el destino del manipulador. Los objetos de registrador pueden agregar cero o más objetos de controlador a ellos mismos con un método addHandler() . Como una situación de ejemplo, una aplicación puede enviar todos los mensajes de registro a un archivo de registro, todos los mensajes de error de registro o superior a stdout, y todos los mensajes críticos a una dirección de correo electrónico . Este escenario requiere tres controladores individuales donde cada controlador es responsable de enviar mensajes de una gravedad específica a una ubicación específica .
Ver http://docs.python.org/library/logging.html#handler-objects para la API Handler
.
En particular, es el método Handler.emit(record)
que puede implementar para especificar el destino de la salida. Presumiblemente, implementaría esto para llamar al TextCtrl.AppendText
.
Aquí es un simple ejemplo de trabajo:
import logging
import random
import sys
import wx
logger = logging.getLogger(__name__)
class WxTextCtrlHandler(logging.Handler):
def __init__(self, ctrl):
logging.Handler.__init__(self)
self.ctrl = ctrl
def emit(self, record):
s = self.format(record) + '\n'
wx.CallAfter(self.ctrl.WriteText, s)
LEVELS = [
logging.DEBUG,
logging.INFO,
logging.WARNING,
logging.ERROR,
logging.CRITICAL
]
class Frame(wx.Frame):
def __init__(self):
TITLE = "wxPython Logging To A Control"
wx.Frame.__init__(self, None, wx.ID_ANY, TITLE)
panel = wx.Panel(self, wx.ID_ANY)
log = wx.TextCtrl(panel, wx.ID_ANY, size=(300,100),
style = wx.TE_MULTILINE|wx.TE_READONLY|wx.HSCROLL)
btn = wx.Button(panel, wx.ID_ANY, 'Log something!')
self.Bind(wx.EVT_BUTTON, self.onButton, btn)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(log, 1, wx.ALL|wx.EXPAND, 5)
sizer.Add(btn, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer)
handler = WxTextCtrlHandler(log)
logger.addHandler(handler)
FORMAT = "%(asctime)s %(levelname)s %(message)s"
handler.setFormatter(logging.Formatter(FORMAT))
logger.setLevel(logging.DEBUG)
def onButton(self, event):
logger.log(random.choice(LEVELS), "More? click again!")
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = Frame().Show()
app.MainLoop()
Captura de pantalla:
Actualización: Como señala iondiode, este script simple puede tener problemas si hay múltiples subprocesos en su aplicación, todos los inicios de sesión a través de dicho controlador; lo ideal es que solo un hilo de interfaz de usuario actualice la interfaz de usuario. Puede usar el enfoque sugerido para registrar el evento mediante un evento personalizado, según su respuesta.
es el registro de línea.Handler .__ init __ (self) ¿correcto?¿Es correcto pasar auto dentro de __init__? – piertoni
- 1. wxPython: cómo hacer que un TextCtrl complete un panel
- 2. Registro de Java: ¿cómo redirigir la salida a un archivo de registro personalizado para un registrador?
- 3. redireccionar std :: cout a un escritor personalizado
- 4. redireccionar stdout al registrador en Python
- 5. Establecer el ancho de un wxPython TextCtrl en número de caracteres
- 6. ¿Cómo puedo obtener google guice para inyectar un registrador personalizado, por ejemplo, un registrador de uso común o log4j logger
- 7. Cómo escribir el controlador de registro de python personalizado?
- 8. ¿Cómo crear un controlador de registro para conectarse a Oracle?
- 9. Implementar registrador personalizado con slf4j
- 10. wxPython - actualizar dynamially un listctrl dependiendo de la entrada en un textctrl
- 11. ¿Cómo puedo redireccionar a una URL?
- 12. ¿Cómo puedo redireccionar a la página actual usando JavaScript?
- 13. ¿Registrador personalizado en Rails 3?
- 14. ¿Cómo puedo redireccionar a otra acción/controlador en MVC3 desde un método VOID?
- 15. ¿Cómo agregar un nivel de registro personalizado al registrador en ruby?
- 16. Cómo agregar un controlador de registro personalizado a Google App Engine?
- 17. ¿Dónde almacena el registrador de raíz Python un registro?
- 18. Cómo instalar wxPython usando virtualenv
- 19. ¿Cómo registro el seguimiento completo de una excepción de Ruby usando el registrador Rails predeterminado?
- 20. ¿Cómo puedo instalar un controlador usando InnoSetup?
- 21. ¿Cómo imprimo solo mensajes de registro para un registrador dado?
- 22. ¿Cómo puedo redireccionar a la acción anterior en ASP.NET MVC?
- 23. ¿Cómo puedo redireccionar stdout a un archivo en tcl
- 24. registrador Singleton, registrador estático, registrador de fábrica ... ¿cómo iniciar sesión?
- 25. ¿Cómo redireccionar javax.mail.Session setDebugOut a log4j logger?
- 26. Utilizando el registro de registros etiquetados, ¿cómo puedo registrar el nivel de registro de un mensaje?
- 27. En wxPython, ¿cómo vincular un evento EVT_KEY_DOWN a toda la ventana?
- 28. Windows C++: ¿Cómo puedo redireccionar stderr para llamadas a fprintf?
- 29. Reemplazar controlador predeterminado de Python registrador
- 30. ¿Cómo registro un IObjectRenderer personalizado en log4net?
@Vinjay Sajip: su respuesta no es segura si los eventos se registran fuera del bucle principal de wx. Es más seguro usar eventos wx para procesar datos de hilos externos. – iondiode
Sin duda tiene razón, pero mi respuesta solo apunta al enfoque que se utilizará en lugar de ofrecer una solución totalmente probada en batalla. –