== Introduction == Some MS Windows applications are available only as console programs. In some cases, it is desirable to be able to display output from such applications in a wxWindow, for review by the user. == What Objects are Involved == As you will see, this recipe involves little in the way of wxPython coding. Rather this recipe presents an adaptation of the usual recipes for connecting to the input and output handles of a running process, so that the output can be sent to a wxWindow. (I adapted the main specifics of this recipe from the win32 distribution of Python and some suggested code for Twisted, from a developers' list.) Two scripts are presented below. The one that involves wxPython merely illustrates how the other one is used. == Process Overview == The console program is run in the usual way. However, the output is processed in a separate thread, so that wxPython need not wait for the program to terminate before displaying its output in the wxWindow. == Special Concerns == This recipe offers only the bare bones, in the interests of simplicity. No provision is made for processing stderr (although that would appear to be easy to do), nor for stdin. == Code Sample == {{{ #!python from wxPython.wx import * # wxPython illustrative driver from runproc import Process if __name__ == "__main__" : class MainFrame ( wxFrame ) : def __init__ ( self, * args ) : wxFrame . __init__ ( self, * args ) tw = wxTextCtrl ( self, -1, style = wxTE_MULTILINE ) tw . SetForegroundColour ( wxGREEN ) tw . SetBackgroundColour ( wxBLACK ) tw . SetFont ( wxFont ( 12, wxSWISS, wxNORMAL, wxBOLD ) ) p = Process ( tw . WriteText ) cmd = 'python printlines.py' p . run ( cmd ) app = wxPySimpleApp ( ) frame = MainFrame ( None, wxNewId ( ), 'Trial run' ) frame . Show ( ) app . MainLoop ( ) # module to provide threaded access # # driver above expects this module to be called 'runproc.py' (say) # and available on the Python path import win32api import win32pipe import win32file import win32process import win32security import win32con import msvcrt import os import threading class Process: def __init__ ( self, outputLineCallback ) : self . outputLineCallback = outputLineCallback def run ( self, cmdline ) : sAttrs = win32security . SECURITY_ATTRIBUTES ( ) sAttrs . bInheritHandle = 1 hStdin_r, self . hStdin_w = win32pipe . CreatePipe ( sAttrs, 0 ) self . hStdout_r, hStdout_w = win32pipe . CreatePipe ( sAttrs, 0 ) self . hStderr_r, hStderr_w = win32pipe . CreatePipe ( sAttrs, 0 ) pid = win32api . GetCurrentProcess ( ) def ReplaceHandle ( handle ) : tmp = win32api . DuplicateHandle ( pid, handle, pid, 0, 0, win32con . DUPLICATE_SAME_ACCESS ) win32file . CloseHandle ( handle ) return tmp self . hStdin_w = ReplaceHandle ( self . hStdin_w ) self . hStdout_r = ReplaceHandle ( self . hStdout_r ) self . hStderr_r = ReplaceHandle ( self . hStderr_r ) StartupInfo = win32process . STARTUPINFO ( ) StartupInfo . hStdInput = hStdin_r StartupInfo . hStdOutput = hStdout_w StartupInfo . hStdError = hStderr_w StartupInfo . dwFlags = win32process . STARTF_USESTDHANDLES # StartupInfo . dwFlags = StartupInfo . dwFlags | win32process . STARTF_USESHOWWINDOW # StartupInfo . wShowWindow = win32con . SW_HIDE hProcess, hThread, dwPid, dwTid = win32process . CreateProcess \ ( None, cmdline, None, None, 1, 0, None, None, StartupInfo ) win32file . CloseHandle ( hStderr_w ) win32file . CloseHandle ( hStdout_w ) win32file . CloseHandle ( hStdin_r ) #~ self.stdin = os.fdopen(msvcrt.open_osfhandle(self.hStdin_w, 0), "wb") self.stdout = os.fdopen(msvcrt.open_osfhandle(self.hStdout_r, 0), "rb") #~ self.stderr = os.fdopen(msvcrt.open_osfhandle(self.hStderr_r, 0), "rb") threading . Thread ( target = self . doReadOut ) . start ( ) def doReadOut ( self ) : while 1: line = self . stdout . readline ( ) if line : self . outputLineCallback ( line [ : -1 ] ) else : break if __name__ == '__main__': def callback ( line ) : print line p = Process ( callback ) exe = win32api . GetModuleFileName ( 0 ) p . run ( exe + ' printlines.py' ) }}} === Comments === I welcome your comments.- [[Bill Bell]] Why not use wx.Process and wx.Execute? You get asynchronous process handling in a single thread that way. Alternatively, you can use the built in subprocess module (in Python 2.4 and later). These options are cross-platform, which your recipe is not. You should also correct your over-use of spaces, which violate all sorts of Python and wxPython style guides. - [[Josiah Carlson]]