使用subprocess.Popen会产生不完整的结果,因为subprocess.call正在提供正确的输出
这与回归脚本有关,回归脚本有6个作业,每个作业执行相同的任务,但是在不同的输入文件上。我使用SubProcess.Popen
并行运行所有内容使用shell脚本执行任务,该脚本调用一堆C编译的可执行文件,其作用是生成一些文本报告,然后将文本报告信息转换为jpg图像
shell脚本示例(runit是文件名),带有调用C-compile可执行文件
#!/bin/csh -f
#file name : runit
#C - Executable 1
clean_spgs
#C - Executable 2
scrub_spgs_all file1
scrub_spgs_all file2
#C - Executable 3
scrub_pick file1 1000
scrub_pick file2 1000
在使用subprocess.Popen时,scrub_spgs_all和scrub_pick都试图并行运行,导致脚本生成不完整的结果,即输出文本文件不包含完整信息,也缺少某些输出文本报告。
subprocess.Popen调用是
resrun_proc = subprocess.Popen("./"+runrescompare, shell=True, cwd=rescompare_dir, stdout=subprocess.PIPE, stderr=subprocess.POPT, universal_newlines=True)
其中runrescompare是一个shell脚本并具有
#!/bin/csh
#some other text
./runit
使用subprocess.call正确生成所有输出文本文件和jpg图像但我无法并行运行所有6个作业。
resrun_proc = subprocess.call("./"+runrescompare, shell=True, cwd=rescompare_dir, stdout=subprocess.PIPE, stderr=subprocess.POPT, universal_newlines=True)
使用python子进程调用从shell脚本调用C-exctuable的正确方法是什么,其中所有6个作业可以并行运行(使用python 3.5.1?
感谢。
答案 0 :(得分:3)
你试图使用subprocess.Popen()来模拟多处理,它不能像你想的那样工作:输出在一段时间后被阻止,除非你使用它,例如使用subprocess.call
(但这是阻塞的)或者读取输出,但循环中有6个并发句柄,你一定会遇到死锁。
最好的方法是在单独的线程中运行import threading,time
lock=threading.Lock()
def func1(a,b,c):
lock.acquire()
print(a,b,c)
lock.release()
time.sleep(10)
tl=[]
t = threading.Thread(target=func1,args=[1,2,3])
t.start()
tl.append(t)
t=threading.Thread(target=func1,args=[4,5,6])
t.start()
tl.append(t)
# wait for all threads to complete (if you want to wait, else
# you can skip this loop)
for t in tl:
t.join()
行。
有几种方法可以做到这一点。带锁定的小例子:
check_output
我花时间创建了一个更适合您需求的示例:
2个线程执行命令并获取输出,然后在锁内打印以避免混淆。我已经使用了import threading,time,subprocess
lock=threading.Lock()
def func1(runrescompare,rescompare_dir):
resrun_proc = subprocess.check_output(runrescompare, shell=True, cwd=rescompare_dir, stderr=subprocess.PIPE, universal_newlines=True)
lock.acquire()
print(resrun_proc)
lock.release()
tl=[]
t=threading.Thread(target=func1,args=["ls","C:/"])
t.start()
tl.append(t)
t=threading.Thread(target=func1,args=["ls","D:/"])
t.start()
tl.append(t)
# wait for all threads to complete (if you want to wait, else
# you can skip this loop)
for t in tl:
t.join()
方法。我正在使用Windows,我并列列出了C和D驱动器。
{{1}}