6

これは、 wx.TextCtrl (または基礎となる GTK+)に関する別のポスト マルチスレッドの問題に関連しています。プライマリ スレッドからの GUI インタラクションの呼び出しを修正した後、パイプ ブロックのバッファリングの問題が再び発生することがわかりました。subprocess.stdoutから自発的な出力を取得する方法は?

要するに、現在、私は subprocess.popen を使用して外部の長時間実行プログラムを起動しています。

    launchcmd=["EXTERNAL_PROGRAM_EXE"]
    p = subprocess.Popen(launchcmd, stdin=subprocess.PIPE, 
            stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    self.outputThread = BashProcessThread(p.stdout.readline)
    self.outputThread.start()
    # wx.TextCtrl is used to make input/output
    self.textctrl = wx.TextCtrl(self, style=wx.TE_PROCESS_ENTER|wx.TE_MULTILINE)

そして、別のスレッドを使用してバックグラウンド プログラムの stdout を読み取り、"wx.CallAfter" でコールバックします。

class BashProcessThread(threading.Thread):
    def __init__(self, readlineFunc, textctrl):
        threading.Thread.__init__(self)
        self.readlineFunc = readlineFunc

    def run(self):
        while True:
           line = self.readlineFunc()
           wx.CallAfter(textctrl.AppendText(line))

上記のコードは、サブプロセスのログ メッセージ block-hanging-block を (行ごとに自発的にではなく) 出力します。最悪の場合、ユーザーが次の入力を送信するまで、残りの 5 ~ 6 行のログ メッセージをタイムリーに出力できませんでした。

私の古い投稿から、pty と pexpect があることを知りました。これにより、サブプロセスが疑似 tty とやり取りしていると見なされる可能性があります。しかし、特にバックグラウンド プロセスが長期にわたる独立した実行中のタスクであることを考えると、pexpect をどのように使用すればよいでしょうか?

例:私が使用した場合

child=pexpect.spawn(launchcmd)

サブプロセスの出力と入力を取得するにはどうすればよいですか? wx.TextCtrl を使用して出力を印刷し、wx.TextCtrl を使用してユーザー入力をサブプロセスに転送できますか?

4

2 に答える 2

13

次のようなことを試しましたか:

child = pexpect.spawn(launchcmd)
while True:
    try:
        child.expect('\n')
        print(child.before)
    except pexpect.EOF:
        break
于 2010-11-17T21:22:16.150 に答える
2

これら 2 つの方法は、ライブ出力を取得するのにうまく機能することがわかりました。

バックグラウンド プロセスのように、ユーザー インタラクションのオプションが必要ない場合は、次のようにします。

child = pexpect.spawn(launchcmd)
child.logfile = sys.stdout
child.expect(pexpect.EOF)
child.close()

バックグラウンド プロセスを使用しておらず、プログラムと対話する機能が必要な場合 (プロンプトが表示された場合)。ここで何が起こるかというと、対話モードに入り、pexpect が画面に直接書き込みます。プログラムが end/EOF に達すると、OSError がスローされます。

child = pexpect.spawn(launchcmd)
try:
    child.interact()
except OSError:
    pass
child.close()    
于 2014-06-11T16:41:03.627 に答える