简体   繁体   中英

Pass Lock object to class that inherits multiprocessing.Process

How can I pass a Lock object to subclass of multiprocessing.Process ? I've tried this and I faced pickling error.

from multiprocessing import Process
from threading import Lock

class myProcess (Process):

    def setLock (self , lock) :
        self.lock = lock

    def run(self) :
        with self.lock :
            # do stuff

if __name__ == '__main__' :
    lock = Lock()
    proc1 = myProcess()
    proc1.setLock(lock)

    proc2 = myProcess()
    proc2.setLock(lock)

    proc1.start()
    proc2.start()

There are many answered questions about passing lock to multiprocessing.Pool but none of them solved my problem with OOP approach usage of Process . If I wanna make a global lock , where should I define it and where can I pass it to myProcess objects ?

You can't use a threading.Lock for multiprocessing, you need to use a multiprocessing.Lock .

You get the pickling-error because a threading.Lock can't be pickled and you are on a OS which uses "spawn" as default for starting new processes (Windows or macOS with Python 3.8+).

Note that on a forking OS (Linux, BSD...), with using threading.Lock , you wouldn't get a pickling error, but the lock would be silently replicated, not providing the synchronization between processes you intended.

Using a separate function for setting the lock is possible, but I would prefer passing it as argument to Process.__init__() along with possible other arguments.

import time
from multiprocessing import Process, Lock, current_process


class MyProcess(Process):

    def __init__(self, lock, name=None, args=(), kwargs={}, daemon=None):
        super().__init__(
            group=None, name=name, args=args, kwargs=kwargs, daemon=daemon
        )
        # `args` and `kwargs` are stored as `self._args` and `self._kwargs`
        self.lock = lock

    def run(self) :
        with self.lock :
            for i in range(3):
                print(current_process().name, *self._args)
                time.sleep(1)


if __name__ == '__main__' :

    lock = Lock()
    p1 = MyProcess(lock=lock, args=("hello",))
    p2 = MyProcess(lock=lock, args=("world",))

    p1.start()
    p2.start()

    p1.join()  # don't forget joining to prevent parent from exiting too soon.
    p2.join()

Output:

MyProcess-1 hello
MyProcess-1 hello
MyProcess-1 hello
MyProcess-2 world
MyProcess-2 world
MyProcess-2 world

Process finished with exit code 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM