Python: combine logging and wx so that logging stream is redirectet to stdout/stderr frame

Posted by Uwe on Stack Overflow See other posts from Stack Overflow or by Uwe
Published on 2010-04-22T09:02:49Z Indexed on 2010/04/22 10:43 UTC
Read the original article Hit count: 916

Filed under:
|
|

Here's the thing:

I'm trying to combine the logging module with wx.App()'s redirect feature. My intention is to log to a file AND to stderr. But I want stderr/stdout redirected to a separate frame as is the feature of wx.App.

My test code:

import logging
import wx

class MyFrame(wx.Frame):
    def __init__(self):
        self.logger = logging.getLogger("main.MyFrame")
        wx.Frame.__init__(self, parent = None, id = wx.ID_ANY, title = "MyFrame")
        self.logger.debug("MyFrame.__init__() called.")

    def OnExit(self):
        self.logger.debug("MyFrame.OnExit() called.")

class MyApp(wx.App):
    def __init__(self, redirect):
        self.logger = logging.getLogger("main.MyApp")
        wx.App.__init__(self, redirect = redirect)
        self.logger.debug("MyApp.__init__() called.")

    def OnInit(self):
        self.frame = MyFrame()
        self.frame.Show()
        self.SetTopWindow(self.frame)
        self.logger.debug("MyApp.OnInit() called.")
        return True

    def OnExit(self):
        self.logger.debug("MyApp.OnExit() called.")

def main():
    logger_formatter = logging.Formatter("%(name)s\t%(levelname)s\t%(message)s")
    logger_stream_handler = logging.StreamHandler()
    logger_stream_handler.setLevel(logging.INFO)
    logger_stream_handler.setFormatter(logger_formatter)
    logger_file_handler = logging.FileHandler("test.log", mode = "w")
    logger_file_handler.setLevel(logging.DEBUG)
    logger_file_handler.setFormatter(logger_formatter)
    logger = logging.getLogger("main")
    logger.setLevel(logging.DEBUG)
    logger.addHandler(logger_stream_handler)
    logger.addHandler(logger_file_handler)
    logger.info("Logger configured.")

    app = MyApp(redirect = True)
    logger.debug("Created instance of MyApp. Calling MainLoop().")
    app.MainLoop()
    logger.debug("MainLoop() ended.")
    logger.info("Exiting program.")

    return 0

if (__name__ == "__main__"):
    main()

Expected behavior is:
- a file is created named test.log
- the file contains logging messages with level DEBUG and INFO/ERROR/WARNING/CRITICAL
- messages from type INFO and ERROR/WARNING/CRITICAL are ether shown on the console or in a separate frame, depending on where they are created
- logger messages that are not inside MyApp or MyFrame are displayed at the console
- logger messages from inside MyApp or MyFrame are shown in a separate frame

Actual behavior is:
- The file is created and contains:

main    INFO    Logger configured.
main.MyFrame    DEBUG   MyFrame.__init__() called.
main.MyFrame    INFO    MyFrame.__init__() called.
main.MyApp  DEBUG   MyApp.OnInit() called.
main.MyApp  INFO    MyApp.OnInit() called.
main.MyApp  DEBUG   MyApp.__init__() called.
main    DEBUG   Created instance of MyApp. Calling MainLoop().
main.MyApp  DEBUG   MyApp.OnExit() called.
main    DEBUG   MainLoop() ended.
main    INFO    Exiting program.

- Console output is:

main    INFO    Logger configured.
main.MyFrame    INFO    MyFrame.__init__() called.
main.MyApp      INFO    MyApp.OnInit() called.
main    INFO    Exiting program.

- No separate frame is opened, although the lines

main.MyFrame    INFO    MyFrame.__init__() called.
main.MyApp      INFO    MyApp.OnInit() called.

shouldget displayed within a frame and not on the console.

It seems to me that wx.App can't redirect stderr to a frame as soon as a logger instance uses stderr as output. wxPythons Docs claim the wanted behavior though, see here.

Any ideas?

Uwe

© Stack Overflow or respective owner

Related posts about wxpython

Related posts about logging