直接子进程输出回主程序的TextCtrl

时间:2014-06-25 18:46:52

标签: wxpython stdout

我有代码在子进程中执行外部文件。在我的主代码中,我将stdout指向TextCtrl。如何重定向外部文件的输出,以便将其输出到TextCtrl?

import wx, sys
from threading import Thread
import time
import subprocess


class mywxframe(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self,None)
        pnl = wx.Panel(self)
        szr = wx.BoxSizer(wx.VERTICAL)
        pnl.SetSizer(szr)
        szr2 = self.sizer2(pnl)
        szr.Add(szr2, 1, wx.ALL|wx.EXPAND, 10)
        log = wx.TextCtrl(pnl, -1, style= wx.TE_MULTILINE, size = (300, -1))
        szr.Add(log, 0, wx.ALL, 10)
        btn3 = wx.Button(pnl, -1, "Stop")
        btn3.Bind(wx.EVT_BUTTON, self.OnStop)
        szr.Add(btn3, 0, wx.ALL, 10)
        self.CreateStatusBar()

        redir = RedirectText(log)
        sys.stdout=redir

        szr.Fit(self)
        self.Show()

    def sizer2(self, panel):
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.tc2 = wx.TextCtrl(panel, -1, 'Set Range', size = (100, -1))
        btn2 = wx.Button(panel, -1, "OK",)
        self.Bind(wx.EVT_BUTTON, self.OnStart, btn2)
        sizer.Add(self.tc2, 0, wx.ALL, 10)
        sizer.Add(btn2, 0, wx.ALL, 10)
        return sizer


    def OnStart(self, event):
        self.p=subprocess.Popen(["C:\Python27\python.exe",'P:\Computing and networking\Python\Learning programs\hello_world.py'])

    def OnStop(self, event):
        self.p.terminate()

    def write(self, *args):
        print args

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

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


app = wx.App()
frm = mywxframe()
app.MainLoop()

我尝试了以下内容:

def OnStart(self, event):
        self.p=subprocess.Popen(["C:\Python27\python.exe",'P:\Computing and networking\Python\Learning programs\hello_world.py'], stdout=subprocess.PIPE)
        while True:
            output = self.p.stdout.readline()
            wx.Yield()
            if output =="":
                pass
            else:
                print output
            if not output: break
        self.p.wait()

但它阻止了GUI,在执行完成之前不打印,并且它不会打印到TextCtrl。帮助

1 个答案:

答案 0 :(得分:0)

如果您的子进程正在创建文件,则需要打开该文件并将行读入TextCtrl。如果子进程正在打印到stdout并且需要一段时间,则需要有一个侦听器线程来监视子进程的标准输出。

此示例不包含您已有的重定向内容,但由于您要从线程打印,因此需要使用wx.CallAfter调用TextCtrl更新。

# spawn the new process, and redirecting stdout and stderr into this process
proc = subprocess.Popen([PathToCurrentPythonInterpreter, pyFilePath],stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1)
proc.stdin.close()
#create new stdout and stderr stream listener objects
m=StreamWatcher()
n=StreamWatcher()

#create new threads for each listener, when the listener hears something it prints it to the GUI console log area
proc1 = Thread(target=m.stdout_watcher, name='stdout-watcher', args=('STDOUT', proc.stdout))
proc1.daemon=True
proc1.start()
proc2 = Thread(target=n.stderr_watcher, name='stderr-watcher', args=('STDERR', proc.stderr))
proc2.daemon=True
proc2.start()


class StreamWatcher:
    def stdout_watcher(self, identifier, stream):
        #for line in stream:
        for line in iter(stream.readline,b''):
            print line
        if not stream.closed:
            stream.close()
        print "-i- Thread Terminating : ", identifier,"\n"

    def stderr_watcher(self, identifier, stream):
        #for line in stream:
        for line in iter(stream.readline,b''):
            #print (identifier, line)
            print "-e- %s" % line
        if not stream.closed:
            stream.close()
        print "-i- Thread Terminating : ", identifier, "\n"