python subprocess.call() 在循环中不执行
我有一段代码,用来生成图表,使用的是gnuplot:
import sys, glob, subprocess, os, time
for file in glob.glob('comb_*.out'):
fNameParts = file[5:].split('.')[0].split('-')
gPlotCmd = []
gPlotCmd = 'unset border; set xl "rotation period #"; set yl "T [K]"\n'
gPlotCmd += 'set key above\n'
gPlotCmd += 'set grid xtics ytics\n'
gPlotCmd += 'set term post eps enh color solid\n'
gPlotCmd += 'set xrange [20:876]\n'
gPlotCmd += 'set output "fig_TestRelax-' + fNameParts[1] + '-' + fNameParts[2] + '-' + fNameParts[3] + '-' + fNameParts[4] + '.eps"\n'
conf = fNameParts[1] + '-' + fNameParts[2] + '-' + fNameParts[3]
gPlotCmd += 'plot "' + file + '" using ($1/36000):($9-$3) w l lw 5 title "OP3-OP1 ' + conf + '", "' + file + '" using ($1/36000):($6-$3) w l lw 3 title "OP2-OP1 ' + conf + '", "' + file + '" using ($1/36000):($9-$6) w l lw 1 title "OP3-OP2 ' + conf + '"'
fw = open('temp.plt','w+')
fw.writelines(gPlotCmd)
subprocess.call(["gnuplot","temp.plt"])
print(file)
在最后一次循环执行时,subprocess.call(["gnuplot","temp.plt"])
这行代码似乎没有被执行。程序结束时,temp.plt文件存在,并且里面有最后一次循环的数据。而且在最后一次循环中,print(file)
这行代码是有执行的。如果我在程序结束后去绘制留下的temp.plt文件,我能看到最后的图表(所以数据这边没有问题)。只有这行 subprocess.call(["gnuplot","temp.plt"])
没有被执行。我还尝试了使用popen来监控输出和错误信息,但这两个都没有内容(和之前的循环一样)。我检查了这个问题,在Linux和Windows上都出现,并且在3.3.5和2.7.3版本中都有。
我得出的结论是,脚本中有些地方出问题了,但我不知道具体是什么。
3 个回答
1
看起来我找到了问题所在。我忘记加 fw.close() 了。最后几行代码应该是这样的:
fw = open('temp.plt','w+')
fw.writelines(gPlotCmd)
fw.close()
subprocess.call(["gnuplot","temp.plt"])
print(file)
现在代码可以正常生成想要的图表了。
4
@lvc和你的回答都是对的;这是一个缓冲问题,使用fw.flush()
可以解决这个问题。不过你不需要临时文件,你可以直接把输入命令传给gnuplot
,而不需要先写到磁盘上:
from subprocess import Popen, PIPE
p = Popen('gnuplot', stdin=PIPE)
p.communicate(input=gPlotCmd.encode('ascii'))
3
这里一个可能的错误是,当你运行gnuplot时,文件temp.plt
实际上并没有写入到磁盘上。Python在调用writelines后,不一定会立即把数据写入文件。这就意味着,当你的脚本启动gnuplot时,它看到的文件是空的。它不会报错,因为空文件并不是错误,而且它也不知道应该期待其他内容。当你在脚本外部运行它时,Python已经退出,所以它的缓冲区里也不会再有任何东西了。
你可以使用with
语句来确保在完成操作后,fw会被关闭:
with open('temp.plt', 'w') as fw:
fw.writelines(gPlotCmd)
subprocess.call(["gnuplot","temp.plt"])