Popen:python 2和3之间的区别

Cho*_*eat 5 python python-2.7 python-3.5

我正在尝试将gnuplot的包装器从python2移植到python3。大多数错误很容易解决,但与项目的通信似乎异常。我在以下(丑陋的)片段中隔离了该问题。

cmd = ['gnuplot']

p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

p.stdin.write("set terminal dumb 80 40\n")
p.stdin.write("plot '-' w p ls 1, '-' w p ls 2, '-' w p ls 3 \n")
p.stdin.write("1 2 3\n")
p.stdin.write("2 3 4\n")
p.stdin.write("\ne\n")
p.stdin.write("e\n")
p.stdin.write("e\n")
while True:
    print(p.stdout.read(1),end="")
Run Code Online (Sandbox Code Playgroud)

此代码可以在python2中工作并产生并打印结果,但在python3中失败。首先,它抱怨字节和字符串,因此我添加universal_newlines=True。从那里我不明白为什么它在stdout上什么也不输出,并在stderr中打印出来: line 4: warning: Skipping data file with no valid points line 5: warning: Skipping data file with no valid points

显然,问题出在编码或通信中,因为我发出的命令是相同的,但我不知道在哪里查找或如何调试。

任何建议都欢迎。

小智 5

与Python 2相比,Python 3在字节和字符串之间有更强的区分。因此,必须将发送到标准输入的字符串编码为字节,并且必须将从标准输出接收的字节解码为字符串。另外,当我尝试您的程序时,我必须p.stdin.close()按照Charles的建议进行添加,以便在gnuplot等待输入时程序不会挂起。

这是我想出的代码的工作版本:

import subprocess

cmd = ['gnuplot']

p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

p.stdin.write("set terminal dumb 80 40\n".encode())
p.stdin.write("plot '-' w p ls 1, '-' w p ls 2, '-' w p ls 3\n".encode())
p.stdin.write("1 2 3\n".encode())
p.stdin.write("2 3 4\n".encode())
p.stdin.write("\ne\n".encode())
p.stdin.write("e\n".encode())
p.stdin.write("e\n".encode())
p.stdin.close()

print(p.stdout.read().decode())
print(p.stderr.read().decode())
Run Code Online (Sandbox Code Playgroud)