我试图在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。
答案 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)
...