I'm trying to port a wrapper for gnuplot from python2 to python3. Most errors are easy to fix but the communication with the project seems to behave unexpectedly. I've isolated the problem in the following (ugly) snippet.
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="")
This code works and produces and print a result in python2 but fails in python3. First it complains about bytes and string, so I add universal_newlines=True
. From there I cannot understand why it outputs nothing on stdout and print this in stderr:
line 4: warning: Skipping data file with no valid points
line 5: warning: Skipping data file with no valid points
Clearly the problem is somewhere in the encoding or communication because the commands I'm issuing are identical but I don't know where to look or how to debug this.
Any suggestion is welcome.
Python 3 is more in-demand and includes a typing system. Python 2 is outdated and uses an older syntax for the print function. While Python 2 is still in use for configuration management in DevOps, Python 3 is the current standard. Python (the code, not the snake) is a popular coding language to learn for beginners.
If you want to determine whether Python2 or Python3 is running, you can check the major version with this sys. version_info. major . 2 means Python2, and 3 means Python3.
While Python 2 had its heyday in the early 2000s, Python 3 is the best choice to learn in 2022. You might find some circumstances in which you need to use Python 2, but on the whole, Python 3 is the most popular language. Since Python 2 was sunsetted in 2020, Python 3 has dominated the programming world.
Python method popen() opens a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'. The bufsize argument has the same meaning as in open() function.
Python 3 makes a stronger distinction between bytes and strings than Python 2. As such, you must encode the strings you are sending to standard input as bytes, and must decode the bytes you receive from standard output to strings. Also, when I tried your program, I had to add p.stdin.close()
as Charles suggested so the program wouldn't hang while gnuplot was waiting for input.
Here's the working version of your code I came up with:
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())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With