Capturing stdout from an imported module in wxpython and sending it to a textctrl, without blocking the GUI

Posted by splafe on Stack Overflow See other posts from Stack Overflow or by splafe
Published on 2012-04-12T15:17:20Z Indexed on 2012/04/12 23:29 UTC
Read the original article Hit count: 216

There are alot of very similar questions to this but I can't find one that applies specifically to what I'm trying to do.

I have a simulation (written in SimPy) that I'm writing a GUI for, the main output of the simulation is text - to the console from 'print' statements. Now, I thought the simplest way would be to create a seperate module GUI.py, and import my simulation program into it:

import osi_model

I want all the print statements to be captured by the GUI and appear inside a Textctrl, which there's countless examples of on here, along these lines:

class MyFrame(wx.Frame):
    def __init__(self, *args, **kwds):
        <general frame initialisation stuff..>

        redir=RedirectText(self.txtCtrl_1)
        sys.stdout=redir

class RedirectText:
    def __init__(self,aWxTextCtrl):
        self.out=aWxTextCtrl

    def write(self,string):
        self.out.WriteText(string)

I am also starting my simulation from a 'Go' button:

def go_btn_click(self, event):
    print 'GO'
    self.RT = threading.Thread(target=osi_model.RunThis())
    self.RT.start()

This all works fine, and the output from the simulation module is captured by the TextCtrl, except the GUI locks up and becomes unresponsive - I still need it to be accessible (at the very minimum to have a 'Stop' button). I'm not sure if this is a botched attempt at creating a new thread that I've done here, but I assume a new thread will be needed at some stage in this process.

People suggest using wx.CallAfter, but I'm not sure how to go about this considering the imported module doesn't know about wx, and also I can't realistically go through the entire simulation architecture and change all the print statements to wx.CallAfter, and any attempt to capture the shell from inside the imported simulation program leads to the program crashing.

Does anybody have any ideas about how I can best achieve this? So all I really need is for all console text to be captured by a TextCtrl while the GUI remains responsive, and all text is solely coming from an imported module.

(Also, secondary question regarding a Stop button - is it bad form to just kill the simulation thread?).

Thanks,

Duncan

© Stack Overflow or respective owner

Related posts about python

Related posts about multithreading