繁体   English   中英

将进程从多处理重定向到单独的wx.TextCtrl

[英]Redirecting processes from multiprocessing to separate wx.TextCtrl

我将使用多处理模块启动四个文本框和最多四个进程。 我可以让进程正常执行,但我真的想将每个进程的所有输出重定向到不同的wx.TextCtrl,这样我就可以看到整个解决方案过程中发生了什么。 我已成功完成了单个线程和sys.stdout重定向,如下所示

http://www.velocityreviews.com/forums/t515815-wxpython-redirect-the-stdout-to-a-textctrl.html

但类似的想法不适用于流程。 有人可以解决这个问题的简单解决方案吗? 我无法想象我是唯一一个遇到过这个问题的人。

据我了解,在wxPython中你通常想从一个线程运行进程。 所以你从进程到线程以及从线程回到wxPython。 我会使用某种命名方案将每个潜在的进程与文本控件(可能是1-4?)相关联,并将其传递给将使用wx.CallAfter或wx.PostEvent告诉wx更新的线程。

您也许可以使用简单的Python套接字服务器来完成此任务。 使用标题向服务器发布消息,该标题指出它属于哪个文本控件。 在wx部分,您可以使用wx.Timer检查套接字服务器是否有新消息,并根据需要进行更新。

对于那些感兴趣的人,这是一个有效的代码片段,可以完成我原来的问题。 它是一种享受。

此代码创建一个包装进程的线程。 在进程的run()函数中,使用重定向类将stderr和stdout重定向到管道。 可以对管道进行酸洗,这是在过程的run()函数中使用它们的先决条件。

只要有输出等待,线程就会坐下并从管道中拉出输出。 从管道中提取的文本使用wx.CallAfter函数写入wx.TextCtrl。 请注意,这是一个非阻塞调用,实际上这里的所有代码都是非阻塞的,这使得响应式GUI成为可能。 注意重定向类中的flush()函数也可以重定向stderr。

注意:有一点需要注意的是,如果您尝试使用过高吞吐量的管道进行读写操作,GUI将会锁定。 但只要你的输出速度相当慢,就没有问题

import wx
import sys
import time
from multiprocessing import Pipe, Process
from threading import Thread

class RedirectText2Pipe(object):
    def __init__(self, pipe_inlet):
        self.pipe_inlet = pipe_inlet
    def write(self, string):
        self.pipe_inlet.send(string)
    def flush(self):
        return None

class Run1(Process):
    def __init__(self, pipe_inlet):
        Process.__init__(self)
        self.pipe_std = pipe_inlet

    def run(self):
        redir = RedirectText2Pipe(self.pipe_std)
        sys.stdout = redir
        sys.stderr = redir

        for i in range(100):
            time.sleep(0.01)
            print i,'Hi'

class RedirectedWorkerThread(Thread):
    """Worker Thread Class."""
    def __init__(self, stdout_target):
        """Init Worker Thread Class."""
        Thread.__init__(self)
        self.stdout_target_ = stdout_target

    def run(self):
        """
        In this function, actually run the process and pull any output from the 
        pipes while the process runs
        """
        pipe_outlet, pipe_inlet = Pipe(duplex = False)
        p = Run1(pipe_inlet)
        p.daemon = True
        p.start()

        while p.is_alive():
            #Collect all display output from process
            while pipe_outlet.poll():
                wx.CallAfter(self.stdout_target_.WriteText, pipe_outlet.recv())

class MainFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self,None)

        self.txt1 = wx.TextCtrl(self, style = wx.TE_MULTILINE|wx.TE_READONLY)
        self.txt2 = wx.TextCtrl(self, style = wx.TE_MULTILINE|wx.TE_READONLY)
        self.txt3 = wx.TextCtrl(self, style = wx.TE_MULTILINE|wx.TE_READONLY)
        self.btn = wx.Button(self, label='Run')
        self.btn.Bind(wx.EVT_BUTTON, self.OnStart)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.AddMany([(self.txt1,1,wx.EXPAND),(self.txt2,1,wx.EXPAND),(self.txt3,1,wx.EXPAND),self.btn])
        self.SetSizer(sizer)

    def OnStart(self, event):
        t1 = RedirectedWorkerThread(self.txt1)
        t1.daemon = True
        t1.start()

        t2 = RedirectedWorkerThread(self.txt2)
        t2.daemon = True
        t2.start()

        t3 = RedirectedWorkerThread(self.txt3)
        t3.daemon = True
        t3.start()

if __name__ == '__main__':
    app = wx.App(False)
    frame = MainFrame() 
    frame.Show(True) 
    app.MainLoop()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM