python - Non-blocking realtime redirection stdout from process to wx.TextCtrl control -
i've got countdown.exe file (source code of file below). when files executed write in console every second text. start execution of file when gui python app executed:
self.countdown_process = subprocess.popen("countdown.exe", shell=true, stdout=subprocess.pipe)
i redirect stdout in subprocess.pipe , start thread out_thread
read stdout of process , add textctrl:
out_thread = outtextthread(self.countdown_process.stdout, self.addtext) out_thread.start()
this full code of python app:
import os import sys import wx import subprocess, threading class myframe(wx.frame): def __init__(self): super(myframe, self).__init__(none) self._init_ctrls() def _init_ctrls(self): self.outtext = wx.textctrl(id=wx.newid(), value='', name='outtext', parent=self, pos=wx.point(0, 0), size=wx.size(0, 0), style=wx.te_multiline|wx.te_rich2) self.outtext.appendtext("starting process...\n") self.outtext.appendtext("waiting 10 seconds...\n") self.countdown_process = subprocess.popen("countdown.exe", shell = true, stdout=subprocess.pipe) out_thread = outtextthread(self.countdown_process.stdout, self.addtext) out_thread.start() def addtext(self, text): self.outtext.appendtext(text) class outtextthread(threading.thread): def __init__(self, std_out, cb): super(outtextthread, self).__init__() self.std_out = std_out self.cb = cb def run(self): text = none while text != '': text = self.std_out.readline() self.cb(text) if __name__ == '__main__': app = wx.app(false) frame = myframe() frame.show(true) app.mainloop()
the c++ code of countdown.exe simple:
#include <stdio.h> #include <time.h> void wait ( int seconds ) { clock_t endwait; endwait = clock () + seconds * clocks_per_sec ; while (clock() < endwait) {} } int main () { int n; printf ("starting countdown...\n"); (n=10; n>0; n--) { printf ("%d\n",n); wait (1); } printf ("fire!!!\n"); return 0; }
but have problem. start python app , must wait 10 second , 10 seconds stdout of countdown.exe written in textctrl can see on picture below: want realtime writing stdout of countdown.exe in textctrl (self.outtext). how can this? tried using wx.callafter in addtext method:
def addtext(self, text): wx.callafter(self.outtext.appendtext, text)
but it's useless.
you cannot call wxpython methods directly thread. line
self.cb(text)
won't work. if put threadsafe method, such wx.callafter, should work. see following links:
- http://wiki.wxpython.org/longrunningtasks
- http://www.blog.pythonlibrary.org/2010/05/22/wxpython-and-threads/
i wrote tutorial on redirecting stuff stdout text control here:
Comments
Post a Comment