python subprocess.call()不在循环中执行

时间:2014-03-30 11:10:29

标签: python python-2.7 python-3.x subprocess

我有以下代码生成带有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并监视stdout和stderr,但两者都是空的(就像在所有其他迭代中一样)。 检查问题是在Linux和Windows以及版本3.3.5和2.7.3中发生的。

我的结论是脚本有问题,但我不知道是什么。

3 个答案:

答案 0 :(得分:4)

@ lvc和你的回答是正确的;这是一个缓冲问题,fw.flush()应该解决它。但是您不需要临时文件,您可以直接将输入命令传递给gnuplot而无需将其写入磁盘:

from subprocess import Popen, PIPE

p = Popen('gnuplot', stdin=PIPE)
p.communicate(input=gPlotCmd.encode('ascii'))

答案 1 :(得分:3)

这里可能出现的一个错误是文件temp.plt在您运行gnuplot时实际上并没有写入磁盘。 Python调用writelines后不必立即刷新缓冲区。这意味着当从脚本启动gnuplot时,它会看到一个空文件。它没有给出错误,因为空输入不是错误,并且它无法知道它对其他任何东西的期望。当你在脚本之外运行它时,Python已经退出,因此无法再在自己的缓冲区中保存任何内容。

使用with语句确保fw在完成后关闭:

with open('temp.plt', 'w') as fw:
    fw.writelines(gPlotCmd)

subprocess.call(["gnuplot","temp.plt"])

答案 2 :(得分:1)

好像我想出来了。我错过了fw.close()。最后一行代码应该是:

fw = open('temp.plt','w+')
fw.writelines(gPlotCmd)
fw.close()
subprocess.call(["gnuplot","temp.plt"])
print(file)

现在代码生成了预期的图。