12
votes

Comment rediriger l'enregistreur sur un TextCtrl WXPYTHON à l'aide d'un gestionnaire de journalisation personnalisé?

J'utilise un module dans mon application python qui écrit un un grand nombre de messages à l'aide du module de journalisation. Au début, j'utilisais cela dans une application console et il était assez facile d'obtenir la sortie de l'enregistrement à afficher sur la console à l'aide d'un gestionnaire de console. Maintenant, j'ai développé une version graphique de mon application avec wxPython et je voudrais afficher toutes les sorties d'enregistrement à un contrôle personnalisé - un textCtrl sur plusieurs lignes. Est-il possible que je pourrais créer un gestionnaire d'enregistrement personnalisé afin que je puisse rediriger tous les messages de syslog il et afficher les messages de journalisation où / mais je veux -. Dans ce cas, une application wxPython


0 commentaires

3 Réponses :


3
votes

Vous aurez besoin de créer une connexion personnalisée.Handler et l'ajouter à votre logging.logger . .

de la documentation:

gestionnaire Les objets sont responsables de Envoi du journal approprié Messages (basé sur les messages du journal ' gravité) au gestionnaire spécifié destination. Les objets d'enregistrement peuvent ajouter zéro ou plus d'objets de gestionnaire à eux-mêmes avec un addhandler () méthode. À titre d'exemple scénario, un L'application peut vouloir envoyer tout le journal messages à un fichier journal, tous les journaux messages d'erreur ou supérieur à stdout, et tous les messages de critique à un adresse e-mail. Ce scénario nécessite Trois manutentionnaires individuels où chacun Le gestionnaire est responsable de l'envoi messages d'une sévérité spécifique à un Emplacement spécifique.

voir http://docs.python.org/library/logging. HTML # Handler-Objects pour le gestionnaire API.

En particulier, il s'agit de la méthode Handler.emit (enregistrement) que vous pouvez implémenter pour spécifier la destination de la sortie. Vraisemblablement, vous impliqueriez cela pour appeler textctrl.appendtext .


0 commentaires

14
votes

Créer un gestionnaire

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()


2 commentaires

@Vinjay Sajip: Votre réponse n'est pas un fil de sécurité si les événements sont connectés à l'extérieur de la boucle principale WX. Il est plus sûr d'utiliser des événements WX pour traiter les données de threads externes.


Nul doute que vous avez raison, mais ma réponse pointe simplement sur l'approche à utiliser plutôt que d'offrir une solution entièrement testée au combat.



4
votes

Voici un exemple de travail simple:

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()


1 commentaires

La ligne journalisation est-elle correcte .__ init __ (auto-) correct? Est-il juste de passer à l'intérieur init ?