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

0 投票
3 回答
1863 浏览
提问于 2025-04-18 00:33

我有一段代码,用来生成图表,使用的是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"])

撰写回答