Python子进程中的stdout文件损坏
我想写一个Python脚本,能够从一个任务列表中运行多个C++程序。
我觉得这个脚本运行得还不错,但我遇到了一个问题,就是输出文件好像坏掉了,打不开。也许你们能帮我解决这个问题。
import multiprocessing
import psutil
import subprocess
import time
jobs2Do = True
while (jobs2Do): #Ever-running program
cpuLoad = cpuLoad + psutil.cpu_percent()
if (cpuLoad < 90):
with open('JobQueue.txt', 'r') as f:
first_line = f.readline()
path = f.readline()
f.close()
if (first_line != ""):
print "Opening " + first_line
process = subprocess.Popen( first_line, shell=True, stdout=open(path,"w"),stderr=open("error.log","w"))
with open('JobQueue.txt', 'r') as fin:
data = fin.read().splitlines(True)
with open('JobQueue.txt', 'w') as fout:
fout.writelines(data[2:])
with open("JobsDone.txt", "a") as myfile:
myfile.write(first_line)
myfile.write(path)
myfile.close()
else:
print "No more jobs... waiting for new jobs...."
time.sleep(10)
好的,我想做的是:我先检查一下CPU有没有空闲的资源,如果有,就打开包含任务的文件,获取文件第一行的命令和第二行的输出路径。这个路径是程序输出结果要保存到的地方。
接着,我想打开这个子进程,把标准输出(stdout)保存到我指定的路径,把错误信息(errorstream)放到其他地方。最后,我会把这个任务从列表中删除,然后重新开始。
现在我的问题是,stdout=open(path,"w")似乎有点问题,因为我无法访问或删除这个文件,但我在文件夹里能看到它。
也许你们能想出我哪里做错了。
谢谢你们的帮助!
NonStopAggroPop
PS:我还想补充一下,这些C++程序运行的时间比较长。所以我本来想做的是让程序执行nohup ./c++ [参数],并把输出流到一个特定的文件,就像我在控制台输入一样。
PPS:我还希望能够在其他程序运行时启动多个C++程序,直到我的CPU使用率达到100%。
1 个回答
我现在的问题是,
stdout=open(path,"w")
似乎有点问题,因为我无法访问或删除它,但我可以在文件夹中看到它。
问题在于 path = f.readline()
返回的字符串末尾有一个换行符。在某些系统上,open(path, 'w')
不在乎这个换行符,还是会创建一个带有换行符的文件。你可以试试 print(os.listdir('.'))
来查看文件名中是否有 \n
。
要解决这个问题,只需去掉换行符:path = path.strip()
。
你的代码中还有其他不相关的问题:
你在缩进时混用了制表符和空格。千万不要这样做:这会导致你看到的缩进和 Python 实际上看到的缩进不一致。你要么一直使用制表符,要么使用空格,不能两者都用。你可以设置编辑器,让按下 Tab 键时插入 4 个空格。
你可能是想用
cpuLoad = psutil.cpu_percent()
,而不是cpuLoad = cpuLoad + psutil.cpu_percent()
,后者在循环的每次迭代中无缘无故地增加。去掉命令中的换行符,并且去掉
shell=True
。除非必要,不要使用 shell(这是个好习惯,虽然在你知道自己在做什么的情况下可以打破):import shlex process = Popen(shlex.split(command), stdout=output_file, stderr=stderr_file)
使用
with
语句,使代码与其他 Python 实现(比如 Jython、Pypy)兼容:with open(path, 'w') as output_file: with open('error.log', 'w') as stderr_file: process = Popen(shlex.split(command), stdout=output_file, stderr=stderr_file)
否则文件可能会在父进程中保持打开状态。
在
with
语句后,去掉f.close()
和myfile.close()
,因为with
语句会自动关闭文件,即使发生异常也是如此,这是它的目的。虽然.close()
是无害的,但在这种情况下是多余的。使用
if not first_line.strip():
来检查第一行是否为空(只包含空白字符)。手动编辑
JobQueue.txt
的想法很脆弱。没有什么能阻止 Python 进程只读取部分输入。你可以使用专门的命令来添加新任务,比如类似at
的工具。你可以根据自己的想法实现,比如在主脚本中监听一个端口以接收新任务,并将任务发送到类似at
的工具。这里有一个关于 Python 中非常基础的套接字客户端和服务器的代码示例。或者使用其他进程间通信的方法。