多处理的实例方法.Pool

时间:2018-01-19 00:20:46

标签: python python-3.x python-multiprocessing

在使用实例方法作为Pool参数时,我一直在使用func对象。关于实例状态,这有点令人惊讶。似乎实例在每个块上都被重置。 E.g:

import multiprocessing as mp
import logging

class Worker(object):
    def __init__(self):
        self.consumed = set()

    def consume(self, i):
        if i not in self.consumed:
            logging.info(i)
            self.consumed.add(i)

if __name__ == '__main__':
    n = 1
    logging.basicConfig(level='INFO', format='%(process)d: %(message)s')
    worker = Worker()

    with mp.Pool(processes=2) as pool:
        pool.map(worker.consume, [1] * 100, chunksize=n)

如果n设置为1,则每次都会记录1。如果n设置为20,则会记录5次,等等。这是什么原因,是否有任何解决方法?我还想将initializer池参数与实例方法一起使用,但遇到了类似的问题。

1 个答案:

答案 0 :(得分:2)

将实例方法worker.consume传递给队列上的工作进程。要做到这一点,必须腌制。对于每个作业,都会收到相同的pickle字符串,但是当该字符串被unpickled时会创建一个新实例。你可以看到这里发生的事情的要点,没有任何多重处理:

In [1]: import pickle

In [2]: class Thing:
   ...:     def __init__(self):
   ...:         self.called = 0
   ...:     def whoami(self):
   ...:         self.called += 1
   ...:         print("{} called {} times".format(self, self.called))

In [3]: pickled = pickle.dumps(Thing().whoami)

In [4]: pickle.loads(pickled)()
<__main__.Thing object at 0x10a636898> called 1 times

In [5]: pickle.loads(pickled)()
<__main__.Thing object at 0x10a6c6550> called 1 times

In [6]: pickle.loads(pickled)()
<__main__.Thing object at 0x10a6bd940> called 1 times

每个Thing实例的ID都不同,每个实例都有自己的called属性。