在Python中管理固定数量的工作者

时间:2012-09-26 03:10:47

标签: python concurrency multiprocessing

我需要实现一个具有主进程的系统,该进程管理执行其他任务的从进程。我有两种不同的从站类型,每个从站需要6个实例。我已经写了一些可行的东西,但它会杀死每个进程并在任务完成时启动一个新进程。这是不可取的,因为产生新过程是昂贵的。我宁愿让每个奴隶作为一个进程运行,并在完成后得到通知,然后使用新输入再次运行它。

我目前的伪代码如下。它并不完美;由于我没有实际的代码,所以我正在为它做准备。

# SlaveTypeB is pretty much the same.
class SlaveTypeA(multiprocessing.Process):
    def __init__(self, val):
        self.value = val
        self.result = multiprocessing.Queue(1)
        self.start()
    def run(self):
        # In real life, run does something that takes a few seconds.
        sleep(2)
        # For SlaveTypeB, assume it writes self.val to a file instead of incrementing
        self.result.put(self.val + 1)
    def getResult(self):
        return self.result.get()[0]


if __name__ == "__main__":
    MAX_PROCESSES = 6
    # In real life, the input will grow as the while loop is being processed
    input = [1, 4, 5, 6, 9, 6, 3, 3]
    aProcessed = []
    aSlaves = []
    bSlaves = []

    while len(input) > 0 or len(aProcessed) > 0:
        if len(aSlaves) < MAX_PROCESSES and len(input) > 0:
            aSlaves.append(SlaveTypeA(input.pop(0))
        if len(bSlaves) < MAX_PROCESSES and len(aProcessed) > 0 :
            bSlaves.append(SlaveTypeB(aProcesssed.pop(0))
        for aSlave in aSlaves:
            if not aSlave.isAlive():
                aProcessed = aSlave.getResult()
                aSlaves.remove(aSlave)
        for bSlave in bSlaves:
            if not bSlave.isAlive():
                bSlaves.remove(bSlave)

我怎样才能使aSlaves和bSlaves中的进程不被杀死和重生。我想我可以使用管道,但是我不知道如何在不必等待的情况下完成阻塞过程。

修改 我用管道重写了这个,它解决了我的问题,因为无法保持进程运行。仍然希望输入最好的方法来做到这一点。我遗漏了slaveB部分,因为只有一种工人类型可以简化问题。

class Slave(Process)
    def __init__(self, id):
        # Call super init, set id, set idlestate = true, etc
        self.parentCon, self.childCon = Pipe()
        self.start()

    def run(self):
        while True:
            input = self.childCon.recv()
            # Do something here in real life
            sleep(2)
            self.childCon.send(input + 1)

   #def isIdle/setIdle():
       # Getter/setter for idle

   def tryGetResult(self):            
       if self.parentCon.poll():
           return self.parentCon.recv()
       return False

   def process(self, input):
       self.parentConnection.send(input)

if __name__ == '__main__'
    MAX_PROCESSES = 6
    jobs = [1, 4, 5, 6, 9, 6, 3, 3]
    slaves = []
    for int i in range(MAX_PROCESSES):
        slaves.append(Slave(i))
    while len(jobs) > 0:
        for slave in slaves:
            result = slave.tryGetResult()
            if result:
                # Do something with result
                slave.setIdle(True)
            if slave.isIdle():
                slave.process(jobs.pop())
                slave.setIdle(False) 

编辑2 知道了,请看下面的答案。

2 个答案:

答案 0 :(得分:0)

创建两个队列? 像worktodoAworktodoB一样,让你的工作人员在等待某些东西被放入队列时闲置,如果放在那里的项目让我们说'退出'他们会退出吗?

否则你应该给tMCs comment一个镜头

答案 1 :(得分:0)

看起来使用SyncManager是这种情况的最佳选择。

类主(SyncManager):     通

输入= [1,4,5,6,9,6,6,3,3] def getNextInput():     #首先检查输入是否为空     return input.pop()

如果名称 ==“主要”:     MAX_PROCESSES = 6     Master.register(“getNextInput”,getNextInput)     m =主人(('localhost',5000))     m.start()     对于范围内的我(MAX_PROCESSES):         奴隶()     而真:         通

class Slave(Process):
    def __init__(self):
        multiprocessing.Process.__init__(self)
        self.start()
    def run(self):
        Master.register("getNextInput", getNextInput)
        m = Master(('localhost', 5000))
        m.connect()
        while True:
            input = m.getNextInput()
            # Check for None first
            self.process(input)
    def process(self):
        print "Processed " + str(input)