Простое решение Python с использованием модуля multiprocessing может выглядеть так:
import os
import multiprocessing
def run_command(cmd):
""" execute cmd via the shell. """
print("starting `{}` ...".format(cmd))
os.system(cmd)
print("end `{}`".format(cmd))
def run_commands(commands, n_parallel):
""" run commands (up to n_parallel in parallel). """
worker = multiprocessing.Pool(n_parallel)
worker.map(run_command, commands)
if __name__ == "__main__":
run_commands([
"program -i input -k 0.1 -m 0.01",
"program -i input -k 0.2 -m 0.22",
"program -i input -k 0.3 -m 3.03",
], n_parallel=2)
Центральным элементом является map()
метод multiprocessing.Pool
. Эта функция принимает список входных значений (в нашем случае, команд оболочки) и передает их в другую функцию, каждая в своем собственном процессе, вплоть до размера параллельных процессов пула.
У этого простого скрипта есть один недостаток: вывод команд оболочки, работающих параллельно, будет перепутан. Этого можно избежать путем захвата и возврата вывода команд в run_command()
, например. используя subprocess.check_output()
вместо os.system()
:
import subprocess
def run_command(cmd):
try:
output = subprocess.check_output(cmd, shell=True)
except subprocess.CalledProcessError:
output = "ERROR in {}".format(cmd)
return output
multiprocessing.Pool.map()
соберет и вернет эти выходные данные в виде списка, который мы можем повторно объединить с командами, чтобы run_commands()
вернул список пар (команда, выход):
def run_commands(commands, n_parallel=2):
worker = multiprocessing.Pool(n_parallel)
for cmd, output in zip(commands, worker.map(run_command, commands)):
print("{}: {}".format(cmd, output))
Теперь, поскольку мы выводим вывод после , когда все параллельные процессы завершены, он не будет перепутан.