Sto usando un modulo nella mia app Python che scrive un sacco di messaggi usando il modulo di registrazione. Inizialmente stavo usando questo in un'applicazione console ed è stato abbastanza facile ottenere l'output di registrazione da visualizzare sulla console usando un gestore di console. Ora ho sviluppato una versione GUI della mia app usando wxPython e mi piacerebbe mostrare tutti gli output di logging a un controllo personalizzato: un testo multi-linea. C'è un modo in cui posso creare un gestore di registrazione personalizzato in modo da poter reindirizzare tutti gli output di registrazione lì e visualizzare i messaggi di registrazione ovunque/comunque voglio - in questo caso, un'app wxPython.Come posso reindirizzare il registratore ad un wxPython textCtrl usando un gestore di registrazione personalizzato?
risposta
Creare 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)
Poi, nel vostro controllo
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()
È necessario creare un numero personalizzato logging.Handler
e aggiungerlo al numero logging.Logger
.
Dalla documentazione:
Handler
oggetti sono responsabili spedizione dei adeguata registro messaggi (sulla base della gravità i messaggi di log) ai specificato destinazione del conduttore. Gli oggetti logger possono aggiungere zero o più oggetti di gestione allo stesso con un metodo addHandler() . Come scenario di esempio, un'applicazione potrebbe voler inviare tutti i messaggi di registro a un file di registro, tutti i messaggi di errore di errore o superiore a stdout, e tutti i messaggi di importanza critica a un indirizzo di posta elettronica . Questo scenario richiede tre singoli gestori in cui ogni gestore è responsabile dell'invio di messaggi di gravità specifica a una posizione specifica .
Vedere http://docs.python.org/library/logging.html#handler-objects per l'API Handler
.
In particolare, è il metodo Handler.emit(record)
che è possibile implementare per specificare la destinazione dell'output. Presumibilmente, dovresti implementarlo per chiamare TextCtrl.AppendText
.
Ecco un semplice esempio di lavoro:
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()
Screenshot:
Aggiornamento: Come indicato da iondiode, questo semplice script potrebbe presentare problemi se nella propria app sono presenti più thread, tutti i registri tramite tale gestore; idealmente solo un thread dell'interfaccia utente dovrebbe aggiornare l'interfaccia utente. Puoi utilizzare l'approccio suggerito per registrare l'evento utilizzando un evento personalizzato, come da sua risposta.
è la registrazione di riga.Handler .__ init __ (self) corretta?È giusto passare dentro __init__? – piertoni
- 1. Registrazione Java: come reindirizzare l'output in un file di registro personalizzato per un logger?
- 2. Come scrivere un gestore di registrazione python personalizzato?
- 3. Registratore Singleton, registratore statico, registratore di fabbrica ... come accedere?
- 4. È possibile limitare TextCtrl per accettare numeri solo in wxPython?
- 5. Impostazione della larghezza di un wxPython TextCtrl in numero di caratteri
- 6. Come ottenere google guice per iniettare un programma di registrazione personalizzato, ad esempio un logger di registrazione delle commons o log4j
- 7. Registrazione del gestore di protocl url personalizzato che Outlook riconosce?
- 8. In wxPython, come si associa un evento EVT_KEY_DOWN all'intera finestra?
- 9. Htaccess reindirizzare ad un altro https https
- 10. Usando un UIWebView, posso usare un carattere personalizzato?
- 11. Generazione di un comando CommandEvent in wxPython
- 12. Come posso eseguire il gestore eventi assegnato a un mock?
- 13. Come ridimensionare e disegnare un'immagine usando wxpython?
- 14. Come posso accedere ad un database Interbase (.IB) usando RubyOnRails?
- 15. Come annullare la registrazione e registrare un gestore eventi attendibile?
- 16. Come posso aggiungere un gestore di URL personalizzato su Windows. Come iTunes itms: //
- 17. Registratore JSch - dove posso configurare il livello
- 18. Come posso annullare la registrazione di un gestore impostato sulla funzione jQuery.ajaxStart()?
- 19. Come posso reindirizzare una pagina php ad un'altra pagina php?
- 20. problemi di visualizzazione di wxBitmaps usando wxPython
- 21. Registrazione di un JsonConverter personalizzato a livello globale in Json.Net
- 22. Come posso utilizzare il gestore ruoli in un servizio WCF?
- 23. registrazione/gestione errori all'interno di un appatore log4net personalizzato
- 24. Come posso aprire un file usando il gestore predefinito della shell?
- 25. Come testare un ModelBinder personalizzato usando Moq?
- 26. Recupero dell'oggetto di richiesta in un gestore di logging Django personalizzato
- 27. Registrazione di un calcolatore di Spree personalizzato non funziona
- 28. Come si associa un gestore di eventi a un dropdown personalizzato di framework di Zurb Foundation?
- 29. Posso estendere l'oggetto console (per reindirizzare la registrazione) in javascript?
- 30. Come posso installare un driver usando InnoSetup?
@Vinjay Sajip: la tua risposta non è sicura se gli eventi vengono registrati al di fuori del ciclo principale di wx. È più sicuro usare gli eventi wx per elaborare i dati da thread esterni. – iondiode
Indubbiamente hai ragione, ma la mia risposta indica solo l'approccio da utilizzare piuttosto che offrire una soluzione completamente testata. –