python多处理调度任务

时间:2013-07-25 11:37:30

标签: python multiprocessing

我有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版本工作正常

4 个答案:

答案 0 :(得分:1)

警告这对部署和情况有点主观,但我目前的设置如下

我有一个工作程序,我启动了6个副本(我有6个核心)。 每个工人都会做以下事情;

  1. 连接到Redis实例
  2. 尝试并弹出特定列表的某些作品
  3. 推回记录信息
  4. “队列”中缺少工作的空闲或终止
  5. 然后每个程序基本上是独立的,同时仍然使用单独的排队系统完成所需的工作。由于您的流程没有中间人,这可能是您解决问题的方法。

答案 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中列出的类型可以被腌制:

  
      
  • NoneTrueFalse
  •   
  • 整数,长整数,浮点数,复数
  •   
  • 普通和Unicode字符串
  •   
  • tuple s,list s,setdict只包含可选对象的离群值
  •   
  • 在模块顶层定义的功能
  •   
  • 在模块顶层定义的内置函数
  •   
  • 在模块顶层定义的类
  •   
  • 此类的实例__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已变成可调用的。插件名称列表用作池的可迭代项,插件的实际确定及其实例化在每个工作进程中完成,类​​实例对象用作每个工作进程的可调用对象。