我有8个CPU核心和200个任务要完成。每项任务都是孤立的。无需等待或分享结果。我正在寻找一种方法来一次运行8个任务/进程(最大值)以及其中一个完成时。剩下的任务将自动启动。
如何知道子进程何时完成并启动新的子进程。首先,我正在尝试使用流程(多处理),很难弄清楚。然后我尝试使用pool和face with pickle问题因为我需要使用动态实例化。
已编辑:添加我的游泳池代码
class Collectorparallel():
def fire(self,obj):
collectorController = Collectorcontroller()
collectorController.crawlTask(obj)
def start(self):
log_to_stderr(logging.DEBUG)
pluginObjectList = []
for pluginName in self.settingModel.getAllCollectorName():
name = pluginName.capitalize()
#Get plugin class and instanitiate object
module = __import__('plugins.'+pluginName,fromlist=[name])
pluginClass = getattr(module,name)
pluginObject = pluginClass()
pluginObjectList.append(pluginObject)
pool = Pool(8)
jobs = pool.map(self.fire,pluginObjectList)
pool.close()
print pluginObjectList
pluginObjectList有点像
[<plugins.name1.Name1 instance at 0x1f54290>, <plugins.name2.Name2 instance at 0x1f54f38>]
PicklingError:无法发现:属性查找内置 .instancemethod失败
但是Process版本工作正常
答案 0 :(得分:1)
警告这对部署和情况有点主观,但我目前的设置如下
我有一个工作程序,我启动了6个副本(我有6个核心)。 每个工人都会做以下事情;
然后每个程序基本上是独立的,同时仍然使用单独的排队系统完成所需的工作。由于您的流程没有中间人,这可能是您解决问题的方法。
答案 1 :(得分:0)
我不是Python中多处理的专家,但我尝试了这个帮助http://www.tutorialspoint.com/python/python_multithreading.htm以及这个http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/1/的一些事情。
例如,您可以使用此方法isAlive
来回答您的问题。
答案 2 :(得分:0)
解决问题的方法很简单。首先,请注意方法无法进行腌制。事实上,只有pickle
's documentation中列出的类型可以被腌制:
None
,True
和False
- 整数,长整数,浮点数,复数
- 普通和Unicode字符串
tuple
s,list
s,set
和dict
只包含可选对象的离群值- 在模块顶层定义的功能
- 在模块顶层定义的内置函数
- 在模块顶层定义的类
- 此类的实例
__dict__
或调用__getstate__()
的结果是可选的(请参阅pickle协议一节) 详情)。[...]
请注意函数(内置和用户定义)被腌制 “完全合格”的名称参考,不按价值 。这意味着 仅腌制函数名称,以及中定义函数的模块名称。既不是函数的代码,也不是函数的代码 它的功能属性是pickle。因此必须是定义模块 可以在unpickling环境中导入,并且模块必须包含 命名对象,否则将引发异常。 [4]
同样,类被命名引用腌制,所以相同 适用于unpickling环境的限制。请注意,都不是 该类的代码或数据被腌制 [...]
显然,一个方法不是在模块顶层定义的函数,因此它不能被腌制。(仔细阅读文档的这一部分以避免未来的pickle问题!)但是替换它是绝对微不足道的。具有全局函数并将self
作为附加参数传递的方法:
import itertools as it
def global_fire(argument):
self, obj = argument
self.fire(obj)
class Collectorparallel():
def fire(self,obj):
collectorController = Collectorcontroller()
collectorController.crawlTask(obj)
def start(self):
log_to_stderr(logging.DEBUG)
pluginObjectList = []
for pluginName in self.settingModel.getAllCollectorName():
name = pluginName.capitalize()
#Get plugin class and instanitiate object
module = __import__('plugins.'+pluginName,fromlist=[name])
pluginClass = getattr(module,name)
pluginObject = pluginClass()
pluginObjectList.append(pluginObject)
pool = Pool(8)
jobs = pool.map(global_fire, zip(it.repeat(self), pluginObjectList))
pool.close()
print pluginObjectList
请注意,由于Pool.map
仅使用一个参数调用给定函数,因此我们必须将self
和实际参数“打包”在一起。要做到这一点,我有zip
ped it.repeat(self)
和原始的可迭代。
如果您不关心调用的顺序,那么使用pool.imap_unordered
可能可以提供更好的效果。但是它返回一个可迭代而不是一个列表,所以如果你想要结果列表,你必须做jobs = list(pool.imap_unordered(...))
。
答案 3 :(得分:0)
我相信这段代码会消除所有酸洗问题。
class Collectorparallel():
def __call__(self,cNames):
for pluginName in cNames:
name = pluginName.capitalize()
#Get plugin class and instanitiate object
module = __import__('plugins.'+pluginName,fromlist=[name])
pluginClass = getattr(module,name)
pluginObject = pluginClass()
pluginObjectList.append(pluginObject)
collectorController = Collectorcontroller()
collectorController.crawlTask(obj)
def start(self):
log_to_stderr(logging.DEBUG)
pool = Pool(8)
jobs = pool.map(self,self.settingModel.getAllCollectorName())
pool.close()
这里发生的事情是Collectorparallel
已变成可调用的。插件名称列表用作池的可迭代项,插件的实际确定及其实例化在每个工作进程中完成,类实例对象用作每个工作进程的可调用对象。