我正在通过Linux上的Python子进程模块运行Perl脚本。使用变量输入多次调用运行脚本的函数。
def script_runner(variable_input):
out_file = open('out_' + variable_input, 'wt')
error_file = open('error_' + variable_input, 'wt')
process = subprocess.Popen(['perl', 'script', 'options'], shell=False,
stdout=out_file, stderr=error_file)
但是,如果我运行此函数,比如两次,第二个进程启动时第一个进程的执行将停止。我可以通过添加
来获得我想要的行为process.wait()
调用脚本后,我真的不会卡住。但是,我想找出为什么我不能使用子进程多次运行脚本,并让脚本并行进行这些计算,而不必等待它在每次运行之间完成。
更新
罪魁祸首并不那么令人兴奋:perl脚本使用了为每次执行重写的公共文件。
然而,我从中学到的教训是垃圾收集器在开始运行后不会删除该进程,因为一旦我将其整理出来,这对我的脚本没有任何影响。
答案 0 :(得分:2)
如果您使用的是Unix,并希望在后台运行多个进程,则可以这样使用subprocess.Popen
:
x_fork_many.py:
import subprocess
import os
import sys
import time
import random
import gc # This is just to test the hypothesis that garbage collection of p=Popen() causing the problem.
# This spawns many (3) children in quick succession
# and then reports as each child finishes.
if __name__=='__main__':
N=3
if len(sys.argv)>1:
x=random.randint(1,10)
print('{p} sleeping for {x} sec'.format(p=os.getpid(),x=x))
time.sleep(x)
else:
for script in xrange(N):
args=['test.py','sleep']
p = subprocess.Popen(args)
gc.collect()
for i in range(N):
pid,retval=os.wait()
print('{p} finished'.format(p=pid))
输出看起来像这样:
% x_fork_many.py
15562 sleeping for 10 sec
15563 sleeping for 5 sec
15564 sleeping for 6 sec
15563 finished
15564 finished
15562 finished
我不确定为什么在不拨打.wait()
时会遇到奇怪的行为。但是,上面的脚本建议(至少在unix上)不需要在列表或集合中保存subprocess.Popen(...)
个进程。无论问题是什么,我都不认为它与垃圾收集有关。
PS。也许你的perl脚本在某种程度上是冲突的,这导致一个在另一个脚本运行时以错误结束。您是否尝试从命令行启动对perl脚本的多次调用?
答案 1 :(得分:1)
你必须调用wait()才能要求“等待”popen的结尾。
由于popen在后台执行perl脚本,如果你不等待(),它将在对象“进程”的生命周期结束时停止...这是在script_runner的末尾。
答案 2 :(得分:1)
正如ericdupo所说,任务被杀死是因为你用一个新的process
对象覆盖你的Popen
变量,并且由于没有更多对你之前的Popen
对象的引用,被垃圾收集器摧毁。您可以通过在某处保留对象的引用来阻止这种情况,例如列表:
processes = []
def script_runner(variable_input):
out_file = open('out_' + variable_input, 'wt')
error_file = open('error_' + variable_input, 'wt')
process = subprocess.Popen(['perl', 'script', 'options'], shell=False,
stdout=out_file, stderr=error_file)
processes.append(process)
这应足以防止您之前的Popen
对象被销毁
答案 3 :(得分:0)
我想你想做
list_process = []
def script_runner(variable_input):
out_file = open('out_' + variable_input, 'wt')
error_file = open('error_' + variable_input, 'wt')
process = subprocess.Popen(['perl', 'script', 'options'], shell=False,
stdout=out_file, stderr=error_file)
list_process.append(process)
#call several times script_runner
for process in list_process:
process.wait()
因此您的流程将并行运行