0

マルチプロセッシングモジュールの使用を開始する4つのテキストボックスと最大4つのプロセスがあります。プロセスを適切に実行することはできますが、ソリューションプロセス全体で何が起こっているかを確認できるように、各プロセスのすべての出力を別のwx.TextCtrlにリダイレクトしたいと思います。私はこれをシングルスレッドとsys.stdoutリダイレクトで正常に実行しました。

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

しかし、同様のアイデアはプロセスでは機能しません。誰かが私にこの問題の簡単な解決策をハックできますか?この問題に遭遇したのは私だけだとは想像できません。

4

2 に答える 2

1

私が理解しているように、wxPythonランドでは、通常、スレッドからプロセスを実行する必要があります。したがって、プロセスからスレッドに通信し、スレッドからwxPythonに戻ります。ある種の命名スキームを使用して、潜在的な各プロセスをテキストコントロール(おそらく1〜4?)に関連付け、それをスレッドに戻します。スレッドは、wx.CallAfterまたはwx.PostEventを使用してwxに更新を指示します。

単純なPythonソケットサーバーを使用してこれを実現できる場合もあります。サーバーが属するテキストコントロールを示すヘッダーを使用して、サーバーにメッセージを投稿します。wxの部分では、wx.Timerでソケットサーバーに新しいメッセージがないかチェックし、必要に応じて更新することができます。

于 2012-06-21T13:40:26.600 に答える
1

興味のある方のために、これが私の最初の質問が尋ねたことを実行する実用的なコードスニペットです。それは御馳走を動作します。

このコードは、プロセスをラップするスレッドを作成します。プロセスのrun()関数内で、stderrとstdoutはリダイレクトクラスを使用してパイプにリダイレクトされます。プロセスのrun()関数内でパイプを使用するための前提条件である、パイプをピクルスにすることができます。

次に、スレッドは、出力が待機している限り、パイプから出力を引き出します。パイプからプルされたテキストは、wx.CallAfter関数を使用してwx.TextCtrlに書き込まれます。これは非ブロッキング呼び出しであり、実際、ここにあるすべてのコードは非ブロッキングであるため、応答性の高いGUIが作成されることに注意してください。stderrもリダイレクトするredirectionクラスのflush()関数に注意してください。

注:注意すべき点の1つは、スループットが高すぎるパイプを使用して読み取りと書き込みを行おうとすると、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()
于 2012-06-30T15:24:35.143 に答える