是否可以按顺序启动Pool进程?

时间:2015-09-14 15:09:38

标签: python multiprocessing

以下代码启动三个进程,它们位于池中以处理20个工作程序调用:

import multiprocessing

def worker(nr):
    print(nr)

numbers = [i for i in range(20)]

if __name__ == '__main__':
    multiprocessing.freeze_support()
    pool = multiprocessing.Pool(processes=3)
    results = pool.map(worker, numbers)
    pool.close()
    pool.join()

有没有办法在序列中启动进程(而不是让它们同时启动),并在每个进程启动之间插入延迟?

如果不使用Pool,我会在循环中使用multiprocessing.Process(target=worker, args=(nr,)).start(),一个接一个地启动它们并根据需要插入延迟。我发现Pool非常有用(与map调用一起),所以如果可能的话,我很乐意保留它。

4 个答案:

答案 0 :(得分:2)

根据documentation,不存在对池化过程的这种控制。但是,你可以用锁来模拟它:

import multiprocessing
import time

lock = multiprocessing.Lock()

def worker(nr):
    lock.acquire()
    time.sleep(0.100)
    lock.release()
    print(nr)

numbers = [i for i in range(20)]

if __name__ == '__main__':
    multiprocessing.freeze_support()
    pool = multiprocessing.Pool(processes=3)
    results = pool.map(worker, numbers)
    pool.close()
    pool.join()

您的3个进程仍将同时启动。好吧,我的意思是你无法控制哪个进程首先开始执行回调。但至少你得到了延迟。这有效地让每个工人开始" (但实际上,继续)按指定的时间间隔。

以下讨论产生的修改:

请注意,在 Windows 上,无法从父进程继承锁定。相反,您可以使用multiprocessing.Manager().Lock()在进程之间传递全局锁定对象(当然还有额外的IPC开销)。全局锁定对象也需要在每个进程中初始化。这看起来像是:

from multiprocessing import Process, freeze_support
import multiprocessing
import time
from datetime import datetime as dt

def worker(nr):
    glock.acquire()
    print('started job: {} at {}'.format(nr, dt.now()))
    time.sleep(1)
    glock.release()
    print('ended   job: {} at {}'.format(nr, dt.now()))

numbers = [i for i in range(6)]

def init(lock):
    global glock
    glock = lock

if __name__ == '__main__':
    multiprocessing.freeze_support()
    lock = multiprocessing.Manager().Lock()
    pool = multiprocessing.Pool(processes=3, initializer=init, initargs=(lock,))
    results = pool.map(worker, numbers)
    pool.close()
    pool.join()

答案 1 :(得分:0)

Couldn't you do something simple like this:

from multiprocessing import Process
from time import sleep

def f(n):
    print 'started job: '+str(n)
    sleep(3)
    print 'ended job: '+str(n)

if __name__ == '__main__':
    for i in range(0,100):
        p = Process(target=f, args=(i,))
        p.start()
        sleep(1)

Result

started job: 0
started job: 1
started job: 2
ended job: 0
started job: 3
ended job: 1
started job: 4
ended job: 2
started job: 5

答案 2 :(得分:0)

你能尝试定义一个慢慢产生价值的函数吗?

def get_numbers_on_delay(numbers, delay):
    for i in numbers:
        yield i
        time.sleep(delay)

然后:

results = pool.map(worker, get_numbers_on_delay(numbers, 5))

我没有测试过,所以我不确定,但试一试。

答案 3 :(得分:0)

由于某些原因,我无法获得锁定答案,所以我以这种方式实现了它。 我意识到问题是陈旧的,但也许其他人也有同样的问题。

它产生类似于锁定解决方案的所有进程,但在工作之前根据进程名称编号休眠。

from multiprocessing import current_process
from re import search
from time import sleep

def worker():
    process_number = search('\d+', current_process().name).group()
    time_between_workers = 5
    sleep(time_between_workers * int(process_number))
    #do your work here

由于给进程的名称似乎是唯一的和增量的,因此根据它来获取进程和休眠的数量。 SpawnPoolWorker-1睡1 * 5秒,SpawnPoolWorker-2睡2 * 5秒等。