gpt4 book ai didi

python - python控制调用外部命令的子进程数

转载 作者:太空狗 更新时间:2023-10-29 17:28:56 24 4
gpt4 key购买 nike

我理解使用 subprocess是调用外部命令的首选方式。

但是如果我想并行运行多个命令,但要限制生成的进程数怎么办?困扰我的是我无法阻止子进程。例如,如果我调用

subprocess.Popen(cmd, stderr=outputfile, stdout=outputfile)

然后该过程将继续,而无需等待 cmd 完成。因此,我无法将其包装在 multiprocessing 库的工作程序中。

例如,如果我这样做:

def worker(cmd): 
subprocess.Popen(cmd, stderr=outputfile, stdout=outputfile);

pool = Pool( processes = 10 );
results =[pool.apply_async(worker, [cmd]) for cmd in cmd_list];
ans = [res.get() for res in results];

然后每个 worker 将在生成子进程后完成并返回。所以我真的不能通过使用Pool来限制subprocess生成的进程数。

限制子流程数量的正确方法是什么?

最佳答案

您不需要多个 Python 进程甚至线程来限制并行子进程的最大数量:

from itertools import izip_longest
from subprocess import Popen, STDOUT

groups = [(Popen(cmd, stdout=outputfile, stderr=STDOUT)
for cmd in commands)] * limit # itertools' grouper recipe
for processes in izip_longest(*groups): # run len(processes) == limit at a time
for p in filter(None, processes):
p.wait()

参见 Iterate an iterator by chunks (of n) in Python?

如果您想限制并行子进程的最大和最小数量,您可以使用线程池:

from multiprocessing.pool import ThreadPool
from subprocess import STDOUT, call

def run(cmd):
return cmd, call(cmd, stdout=outputfile, stderr=STDOUT)

for cmd, rc in ThreadPool(limit).imap_unordered(run, commands):
if rc != 0:
print('{cmd} failed with exit status: {rc}'.format(**vars()))

一旦任何limit 子进程结束,就会启动一个新的子进程,以始终保持limit 个子进程。

或使用 ThreadPoolExecutor :

from concurrent.futures import ThreadPoolExecutor # pip install futures
from subprocess import STDOUT, call

with ThreadPoolExecutor(max_workers=limit) as executor:
for cmd in commands:
executor.submit(call, cmd, stdout=outputfile, stderr=STDOUT)

这是一个简单的线程池实现:

import subprocess
from threading import Thread

try: from queue import Queue
except ImportError:
from Queue import Queue # Python 2.x


def worker(queue):
for cmd in iter(queue.get, None):
subprocess.check_call(cmd, stdout=outputfile, stderr=subprocess.STDOUT)

q = Queue()
threads = [Thread(target=worker, args=(q,)) for _ in range(limit)]
for t in threads: # start workers
t.daemon = True
t.start()

for cmd in commands: # feed commands to threads
q.put_nowait(cmd)

for _ in threads: q.put(None) # signal no more commands
for t in threads: t.join() # wait for completion

为避免过早退出,添加异常处理。

如果您想在字符串中捕获子进程的输出,请参阅 Python: execute cat subprocess in parallel .

关于python - python控制调用外部命令的子进程数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9808714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com