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

时间:2015-07-17 15:43:29

标签: python subprocess stdout stdin stderr

我试图在python脚本中与另一个python解释器进行通信。我写了一个对象,它应该存储子进程并读/写它的stdin,stdout,stderr。

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并刷新它。我使用简单的echo脚本测试了这个:

while True:
    print(input())

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

我的问题是,这不适用于python解释器。我试图把所有东西都写到它的stdin上,但是它并没有写任何东西给stdout,stderr。

1 个答案:

答案 0 :(得分:1)

我做了一些测试,你的代码按照我的预期运行。这意味着您正确创建了一个python解释器并将命令传递给它,并且解释器正确执行它们。

问题是输出到管道可能会被缓冲(并且在这里)。如果你正在编写几个kbytes,你可以得到开头部分,但是在这里,在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'

正如JFSebastian在其评论中所建议的那样,不被缓冲困扰的最直接方式就是要求解释者不要使用-u选项或使用PYTHONUNBUFFERED来缓冲任何内容。环境变量:

class Python:

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