Search code examples
pythonpython-2.7logginggtkpygtk

Logging messages to pygtk.entry


I am currently developing gtk GUI for my python Application. I want to implement simple text entry which will contain all logging messages of application (something like console logging window in GUI). Unfortunately, I was only able to create logging handler that will print logging messages to a file or into console input:

def create_logger(logfile):
    logger = logging.getLogger("MyApp")

    file_logging = logging.FileHandler(logfile)
    file_logging.setLevel(logging.INFO)
    logger.addHandler(file_logging)

    console_logging = logging.StreamHandler()
    console_logging.setLevel(logging.INFO)
    logger.addHandler(console_logging)

return logger

Is there any way to set up logger handler that will log messages into Gtk Entry?


Solution

  • If you want a simple solution, I'd recommend using a GtkLabel. The Label can show multi-line texts, and, if you want to highlight something, Label also accepts Markup (HTML-like tags).

    A more complicated approach is using the GtkTextView widget. Basically you write to a GtkTextBuffer, which you previously connected to the GtkTextView to show it on-screen. With this widget you have a lot more possibilities, which you pay for with more complexity.

    Here's an example. It's long because of the MainWindow creation necessary to make it runnable. Use the Label and packing properties to align the text where you'd like it.

    import logging
    import pygtk
    import gtk
    
    class MyHandler(logging.Handler):
        def __init__(self, label):
            logging.Handler.__init__(self)
            self.label = label
    
        def handle(self, rec):
            original = self.label.get_text()
            self.label.set_text(rec.msg + "\n" + original)
    
    class MyLogger():
        def __init__(self, label):
            self.logger = logging.getLogger("Example")
            self.handler = MyHandler(label)
            #self.handler.setLevel(logging.INFO)
            self.logger.addHandler(self.handler)
    
        def warning(self, msg):
            self.logger.warning(msg)
    
    
    class MainWindow(gtk.Window):
        def __init__(self):
            gtk.Window.__init__(self)
            self.set_size_request(200, 100)
            self.connect("delete-event", self.on_delete_event)
    
            self.loglabel = gtk.Label()
            self.add(self.loglabel)
    
            self.show_all()
    
        def run(self):
            gtk.mainloop()
    
        def on_delete_event(self, w, d):
            gtk.main_quit()
    
    
    def main():
        mw = MainWindow()
    
        logger = MyLogger(mw.loglabel)
        logger.warning("This is a test message")
        logger.warning("This is another message")
    
        mw.run()
        return 0
    
    if __name__ == '__main__':
        main()
    

    The log entries are added somewhat artificially in the main program, else I'd have to add more widget. I've overridden the warning method to show how to do it. You can also override the info, and other handlers.

    Note, as user4815162342 pointed out below, the method of using a label might not be optimal for very long logs. You can use a gtk.TextBuffer to do the same, or improve the above program by saving a copy of the text in the handler, adding the new message to it, and re-loading the Label's text.

    Anyway, I suspect that the question was about how to send the log texts to somewhere else but a file or the terminal.