I've been trying to use Python 3.4 to call a simple gnuplot script and then display the result (a .ps file) using evince. My code looks like this:
plotfile = "plot.p"
with open(plotfile, "w") as plt:
lines = ['set term postscript',
'set output "speed.ps"',
'set xlabel "Time"',
'set ylabel "Speed"',
"plot '{}' u 2:4 title 'speed' with lines".format(infile)
]
lines = map(lambda x: x + '\n', lines)
plt.writelines(lines)
# Call gnuplot and evince
subprocess.call(['gnuplot', plotfile])
subprocess.call(['evince', 'speed.ps'])
However, evince
often doesn't display the file. I can create the file correctly using
process = subprocess.Popen(['gnuplot', plotfile])
but if I try to immediately open the file, by calling
process = subprocess.Popen(['gnuplot', plotfile])
subprocess.Popen(['evince', plot.ps])
the file often doesn't display correctly, I'm assuming because the first command doesn't finish in time. To fix this issue, I've tried
process = subprocess.call(['gnuplot', plotfile])
or
process = subprocess.Popen(['gnuplot', plotfile])
process.wait()
but it both cases no .ps file is even created. The only thing that works (and not always) is
process = subprocess.Popen(['gnuplot', plotfile])
time.sleep(1)
subprocess.Popen(['evince', plot.ps])
but that is really ugly.
So my questions are:
1) Why might waiting for the process to finish (using either subprocess.call()
or wait()
) prevent the .ps file from even being created?
2) Is there some solution that doesn't involve using "sleep"?
Versions:
- CentOS 6.6
- Python 3.4
- Gnuplot 4.6
- Evince 2.28.2
I believe you've had some misleading test results leading you down the wrong path. Using
subprocess.call()
or calling.wait()
on aPopen
object does genuinely wait for the program that was invoked to exit. What's not guaranteed, however, is whether the result of yourplt.writelines()
calls will be flushed to disk or will still be in an in-memory buffer by the timegnuplot
is started.Given the following code:
...absent the
flush()
, theplt
file isn't guaranteed to have all contents flushed beforesubprocess.call()
is invoked; lines can still be buffered and not available to other programs yet.Closing a file flushes it, so moving the
call()
s outside thewith
block will also solve your problem.