Subprocess.Popen vs .call:使用python从shell脚本调用C-executable的正确方法是什么,其中所有6个作业可以并行运行

时间:2016-08-29 20:49:55

标签: python-3.x subprocess

使用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?

感谢。

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}}