Redirecting text output from Python functions

Two posts ago, I described how I wrote a function in Python that reads in a binary file from Labview. In my last post, I described using wxPython to write a GUI to process the data from those binary files. Naturally, I called the binary-file-reader function from the GUI. The problem is that the file reader prints a lot of information to the terminal, using Python print statements. None of this goes to the GUI, requiring the user to run the GUI from a terminal and keep an eye on the text output, which is inconvenient. However, I don’t want to modify the file reader to include GUI-specific code, because that would be less modular and less re-usable. Instead, I learned that Python has a very easy facility to redirect stdout, the default destination of the print statement. I modified the file reader as follows:

def readWGMfile(binaryFile, readSecondDerivatives, output=None):
    if output is not None:
        # allow the caller to hand in an alternative to standard out--for example, if
        # the caller is a GUI, redirect "print" statements to a GUI control
        print "Redirecting output..."
        import sys
        sys.stdout = output

    # rest of the function... 

I added an optional argument to the file reader, allowing the caller to specify an object to replace stdout. The sys module is then used to redirect stdout to the object specified by the caller. There’s no change to the default usage of the function, but it’s a lot more flexible. Here is the object that I defined to capture the text:

class Monitor:
    """The Monitor class defines an object which is passed to the function readWGMfile(). Standard
    output is redirected to this object."""

    def __init__(self, notifyWindow):
        import sys
        self.out = sys.stdout
        self._notifyWindow = notifyWindow        # keep track of which window needs to receive events

    def write(self, s):
        """Required method that replaces stdout."""
        if s.rstrip() != "":        # don't need to be passing blank messages
        #            self.out.write("Posting string: " + s.rstrip() + "n")
        wx.PostEvent(self._notifyWindow, TextMessageEvent(s.rstrip()))

The only requirement of the Monitor class is that it implement a write(self, string) method that accepts a string that would otherwise have gone to standard out. In my case, I post a special event which is sent to the specified window. Here is the definition of that event:

class TextMessageEvent(wx.PyEvent):
    """Event to notify GUI that somebody wants to pass along a message in the form of a string."""
    def __init__(self,message):
        wx.PyEvent.__init__(self)
        self.SetEventType(TEXT_MESSAGE)
        self.message = message

Once again, I’m impressed with the way that Python makes hard things easy and very hard things possible. In my next post, I’ll give a quick example of how easy it is “thread” things in Python.

Advertisements

One thought on “Redirecting text output from Python functions

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s