Python(Windows)中父子进程之间的持续通信? [英] Continuous communication between parent and child subprocess in Python (Windows)?

查看:745
本文介绍了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())

在直到我得到的第二个输入之前都可以正常工作

which works fine until the second input where I get:

ValueError: Cannot send input after starting communication

在Windows中是否可以在父进程和子进程之间发送多条消息?

Is there a way to have multiple messages sent between the parent and child process in Windows ?


我无权访问myProgram.exe
的源代码 这是一个交互式命令行应用程序,可从查询中返回结果
in.txt上运行>> myProgram.exe < in.txt > out.txt可以正常工作:


I don't have access to the source code of myProgram.exe
It is an interactive command line application returning results from queries
Running >> myProgram.exe < in.txt > out.txt works fine with in.txt:

query1;
query2;
query3;

推荐答案

通过stdin/stdout与另一个正在运行的进程进行交互

为模拟用例,其中Python脚本启动了命令行交互过程,并通过stdin/stdout发送/接收文本,我们有一个主脚本,该脚本启动了另一个运行简单的交互循环的Python过程.

To simulate the use case where a Python script starts a command line interactive process and sends/receives text over stdin/stdout, we have a primary script that starts another Python process running a simple interactive loop.

这还可以用于Python脚本需要启动另一个进程并仅读取其输出而又没有任何交互作用的情况.

This can also be applied to cases where a Python script needs to start another process and just read its output as it comes in without any interactivity beyond that.

主要脚本

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']

此问题与解答被用来模拟来自目标进程的非阻塞读取: https://stackoverflow.com/a/4896288/7915759

This Q&A was leveraged to simulate non-blocking reads from the target process: https://stackoverflow.com/a/4896288/7915759

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

This method provides a way to check for output without blocking in the main thread; q.empty() will tell you if there's no data. You can play around with blocking calls too using q.get() or with a timeout q.get(2) - the parameter is number of seconds. It can be a float value less than zero.

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

Text based interaction between processes can be done without the thread and queue, but this implementation gives more options on how to retrieve the data coming back.

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

The Popen() parameters, bufsize=1 and encoding='utf-8' make it possible to use <stdout>.readline() from the primary script and sets the encoding to an ascii compatible codec understood by both processes (1 is not the size of the buffer, it's a symbolic value indicating line buffering).

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

With this configuration, both processes can simply use print() to send text to each other. This configuration should be compatible for a lot of interactive text based command line tools.

这篇关于Python(Windows)中父子进程之间的持续通信?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆