Python (Windows) 中父子进程之间的持续通信?

Continuous communication between parent and child subprocess in Python (Windows)?

我有这个脚本:

import subprocess

p = subprocess.Popen(["myProgram.exe"],
                     stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE)
while True:
    out, _ = p.communicate(input().encode())
    print(out.decode())

在我得到的第二个输入之前工作正常:

ValueError: Cannot send input after starting communication

有没有办法在 Windows 中的父进程和子进程之间发送多条消息?

[编辑]
我无法访问 myProgram.exe
的源代码 它是一个交互式命令行应用程序,返回查询结果
运行 >> myProgram.exe < in.txt > out.txt 适用于 in.txt:

query1;
query2;
query3;

通过 stdin/stdout

与另一个 运行 进程交互

为了模拟 Python 脚本启动命令行交互过程并且 sends/receives 文本覆盖 stdin/stdout 的用例,我们有一个启动另一个 Python 的主脚本] 处理 运行 一个简单的交互式循环。

这也适用于 Python 脚本需要启动另一个进程并在它进入时读取它的输出而没有任何交互的情况。

初级脚本

import subprocess
import threading
import queue
import time

if __name__ == '__main__':

    def enqueue_output(outp, q):
        for line in iter(outp.readline, ''):
            q.put(line)
        outp.close()

    q = queue.Queue()

    p = subprocess.Popen(["/usr/bin/python", "/test/interact.py"],
                         stdin    = subprocess.PIPE,
                         stdout   = subprocess.PIPE,
                         # stderr   = subprocess.STDOUT,
                         bufsize  = 1,
                         encoding ='utf-8')

    th = threading.Thread(target=enqueue_output, args=(p.stdout, q))
    th.daemon = True

    th.start()

    for i in range(4):

        print("dir()", file=p.stdin)

        print(f"Iteration ({i}) Parent received: {q.get()}", end='')
        # p.stdin.write("dir()\n")
        # while q.empty():
        #     time.sleep(0)
        # print(f"Parent: {q.get_nowait()}")

interact.py 脚本

if __name__ == '__main__':

    for i in range(2):

        cmd = raw_input()

        print("Iteration (%i) cmd=%s" % (i, cmd))

        result = eval(cmd)

        print("Iteration (%i) result=%s" % (i, str(result)))

输出

Iteration (0) Parent received: Iteration (0) cmd=dir()
Iteration (1) Parent received: Iteration (0) result=['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'cmd', 'i']
Iteration (2) Parent received: Iteration (1) cmd=dir()
Iteration (3) Parent received: Iteration (1) result=['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'cmd', 'i', 'result']

此问答用于模拟目标进程的非阻塞读取:

此方法提供了一种在主线程中不阻塞地检查输出的方法; q.empty() 会告诉您是否没有数据。您也可以使用 q.get() 或超时 q.get(2) 来阻止调用 - 参数是秒数。它可以是一个小于零的浮点值。

进程之间基于文本的交互可以在没有线程和队列的情况下完成,但是这个实现提供了更多关于如何检索返回数据的选项。

Popen() 参数,bufsize=1encoding='utf-8' 使得可以从主脚本使用 <stdout>.readline() 并将编码设置为两者都能理解的 ascii 兼容编解码器进程(1不是缓冲区的大小,它是一个符号值,表示行缓冲)。

使用此配置,两个进程都可以简单地使用 print() 相互发送文本。此配置应该与许多基于交互式文本的命令行工具兼容。