使用 python 的子进程模块打开一个 python 进程

Open a python process using python's subprocess module

我正在尝试在 python 脚本中与不同的 python 解释器进行通信。我写了一个对象,它应该存储子进程和 read/write 它的标准输入、标准输出、标准错误。

import subprocess
import fcntl
import os

class Python:

    def __init__(self):
        self.process = subprocess.Popen("python", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        fcntl.fcntl(self.process.stdout, fcntl.F_SETFL, os.O_RDONLY | os.O_NONBLOCK)
        fcntl.fcntl(self.process.stderr, fcntl.F_SETFL, os.O_RDONLY | os.O_NONBLOCK)

    def read(self):
        stdout = self.process.stdout.read()
        if stdout:
            print("stdout:", stdout)
        stderr = self.process.stderr.read()
        if stderr:
            print("stderr:", stderr)

    def exec(self, line):
        self.process.stdin.write(bytes((line + "\n").encode("ascii")))
        self.process.stdin.flush()

在 init 函数中创建子进程并将 stdout、stderr 设置为非阻塞模式。 read 函数只是暂时将 stdout、stderr 打印到屏幕上,exec 函数将一行写入 python 的 stdin 并将其刷新。我使用一个简单的回显脚本对此进行了测试:

while True:
    print(input())

我能够使用我的 exec 方法,稍后使用 read 方法读取我传递给 exec 方法的行。

我的问题是这不适用于 python 解释器。我试图将所有内容写入其标准输入,但它没有将任何内容写入标准输出、标准错误。

好吧,我做了一些测试,您的代码可以正常工作。这意味着您正确地创建了一个 python 解释器并将命令传递给它,并且解释器正确地执行了它们。

问题是管道的输出可能会被缓冲(在此处)。如果你正在写几千字节,你可以得到开始部分,但在这里,在 Python 解释器退出之前,实际上什么都没有写入管道。

确认方式:

p = Python()
p.exec("print('foo')")
p.exec("print('bar')")
p.process.stdin.close() # force interpreter to exit ...
time.sleep(0.1) # wait for the interpreter to exit ...
p.read()

你应该得到 stdout: b'foo\r\nbar\r\n'


正如 J.F.Sebastian 在其评论中所建议的那样,不被缓冲打扰的最直接的方法就是简单地要求解释器不要缓冲任何东西,使用 -u 选项或使用PYTHONUNBUFFERED 环境变量:

class Python:

    def __init__(self):
        self.process = subprocess.Popen("python -u", stdin=subprocess.PIPE,
                                         stdout=subprocess.PIPE,
                                         stderr=subprocess.PIPE)
        ...