锁对象只能通过继承在进程之间共享

Fil*_*ter 5 python pool multiprocessing

我正在multiprocessing.Pool对象中使用该类并尝试执行以下操作:

from multiprocessing import Lock, Pool

class A:
    def __init__(self):
        self.lock = Lock()
        self.file = open('test.txt')
    def function(self, i):
        self.lock.acquire()
        line = self.file.readline()
        self.lock.release()
        return line
    def anotherfunction(self):
        pool = Pool()
        results = pool.map(self.function, range(10000))
        pool.close()
        pool.join()
        return results
Run Code Online (Sandbox Code Playgroud)

但是,我收到一个运行时错误,指出锁对象只能通过继承在进程之间共享。我对 Python 和多处理相当陌生。我怎样才能走上正确的轨道?

Boo*_*boo 9

multiprocessing.Lock实例可以是multiprocessing.Process实例的属性。当主进程中创建一个带有锁属性的进程时,该锁存在于主进程\xe2\x80\x99s地址空间中。当调用 process\xe2\x80\x99sstart方法并运行调用 process\xe2\x80\x99srun方法的子进程时,必须将锁序列化/反序列化到子进程地址空间。这按预期工作:

\n
from multiprocessing import Lock, Process\n\nclass P(Process):\n    def __init__(self, *args, **kwargs):\n        Process.__init__(self, *args, **kwargs)\n        self.lock = Lock()\n    def run(self):\n        print(self.lock)\n\nif __name__ == \'__main__\':\n    p = P()\n    p.start()\n    p.join()\n
Run Code Online (Sandbox Code Playgroud)\n

印刷:

\n
<Lock(owner=None)>\n
Run Code Online (Sandbox Code Playgroud)\n

不幸的是,当您处理实例时,这不起作用multiprocessing.Pool。在您的示例中,self.lock是通过该方法在主进程中创建的__init__。但是,当Pool.map调用 invoke时self.function,锁无法序列化/反序列化到将运行此方法的已在运行的池进程。

\n

解决方案是使用设置为该锁的全局变量来初始化每个池进程(现在将该锁作为该类的属性是没有意义的)。实现此目的的方法是使用pool 方法的初始化程序和initargs__init__参数。请参阅文档

\n
from multiprocessing import Lock, Pool\n\ndef init_pool_processes(the_lock):\n    \'\'\'Initialize each process with a global variable lock.\n    \'\'\'\n    global lock\n    lock = the_lock\n\nclass Test:\n    def function(self, i):\n        lock.acquire()\n        with open(\'test.txt\', \'a\') as f:\n            print(i, file=f)\n        lock.release()\n    def anotherfunction(self):\n        lock = Lock()\n        pool = Pool(initializer=init_pool_processes, initargs=(lock,))\n        pool.map(self.function, range(10))\n        pool.close()\n        pool.join()\n\nif __name__ == \'__main__\':\n    t = Test()\n    t.anotherfunction()\n
Run Code Online (Sandbox Code Playgroud)\n