因此,我有一个构建命令列表的脚本,然后将其提供给Popen以并行启动。这可以按我预期的那样工作-但我正在尝试编写一些可以同时运行有限数量(而不是全部)的东西。我已经走了这么远:
#! /usr/bin/env python3
import subprocess
from multiprocessing import Pool
cmd_list = []
cmd_list.append(['echo','zero', 'one'])
cmd_list.append(['echo','one'])
cmd_list.append(['echo','two']) # and so on...
# each entry in cmd_list can now be run in a subprocess/subshell
pidlist = []
for cmd in cmd_list:
pid = subprocess.Popen(cmd)
pidlist.append(pid)
for cmd in cmd_list:
pid.wait()
pool = Pool(2)
## map or apply or queue or something here so I run only two "cmd"s until they're all done...
我一直在疯狂地搜索,并使用map
和apply
以及worker和queues
找到了很多示例,坦率地说,这似乎有点多-我认为我有足够的经验python知道必须有一种更简单的方法来解决此问题,而无需重新整理所有命令字符串(在我的情况下,它可以是数百个字符长,但是它们 都被格式化为您将列表传递给Popen,它将运行;-)
描述该行为的另一种方法在功能上等同于在unix xargs命令中使用-P <n>
自变量...
编辑:想扩展此范围,以允许将一组args(kwargs)传递到池进程中。我现在有下面的代码块可以工作:
def spawn(cmd):
pid = subprocess.Popen(cmd)
pid.wait()
pool = Pool(3)
pool.map(spawn, cmd_list) # happily kicks of three subprocesses and runs...
但是我希望能够将其他参数传递给spawn调用,在这种特殊情况下,我希望能够将优先级或std {in,out,err}重定向之类的东西传递给Popen调用。我尽力在函数签名中尝试一堆** kwargs的不同组合,但是什么也做不了。我从这里开始,希望它能表达我所追求的行为:
def spawnWithOpts(cmd, **kwargs):
pid = subprocess.Popen(cmd, **kwargs)
pid.wait()
pool.starmap(spawnWithOpts, cmd_list, "stderr=subprocess.STDOUT")
这等同于将spawn的定义更改为:
def spawn(cmd):
pid = subprocess.Popen(cmd, stderr=subprocess.STDOUT)
pid.wait()
但是,显然,我希望能够根据我所遵循的确切行为将任意一组参数传递给'spwan'包装函数。
答案 0 :(得分:1)
您已经有了命令列表,现在创建一个执行单个命令的函数,并将其映射到您的池中:
def cmd_executor(cmd):
pid = subprocess.Popen(cmd)
pid.wait()
pool = Pool(2)
results_list = pool.map(cmd_executor, cmd_list)
这会将您的列表成员一次映射到该函数,
如果您不想使用100个进程(假设,我现在知道现在限制为2个),则可以将multiproc导入更改为使用from multiprocessing.dummy import Pool
-使用线程而不是进程,这样可能会更有效,因为subprocess
负责实际产生新进程。
答案 1 :(得分:0)
好,这就是我最终解决的问题,它解决了我的紧迫问题,我想足够通用,我可以灵活运用一些前进的方向:
const arr = [{ prop: 3 }, { prop: 4 }];
const pointer = new Proxy([], {
get(target, prop, receiver) {
// if the prop is a string that can be converted to a number
// return the corresponding value from the arr
if(typeof prop === 'string' && !isNaN(Number(prop))) return arr[target[prop]];
return Reflect.get(target, prop, receiver);
}
});
pointer.push(0, 1);
console.log(pointer);
arr.splice(0, 0, { prop: 1 });
console.log(pointer);
对我来说,诀窍是最终理解import subprocess
from multiprocessing.dummy import Pool
from functools import partial
def spawn(cmd, **kwargs):
pid = subprocess.Popen(cmd, **kwargs)
pid.wait()
pool = Pool(3)
cmd_list=[]
for x in range(5):
cmd_list.append(['echo',str(x)])
# run without any kwargs, so just the basic Popen call...
pool.map(spawn, cmd_list)
# now add some arguments to the Popen call
kwargs={}
kwargs['stderr'] = subprocess.STDOUT
kwargs['startupinfo'] = None
# and now call it with those kwargs, using 'partial'...
pool.map( partial(spawn, **kwargs) ,cmd_list)
is its own special operator,并且除了“表示未打包的关键字参数列表”这一非常特定的目的外,没有任何轴承。我认为它是字符串,列表甚至是字典是错误的(尽管您使用字典来构建基本kwarg)-它仅用于解压缩参数。我敢肯定,对于使用它的人来说,这是显而易见的,但是对我而言,直到我理解了这个概念之后,整个事情才变得有意义。如丹尼尔(Danielle)上面显示的,对**kwargs
的调用使我可以正确保留partial(spawn, **kwargs)
的签名。