Передайте объект Lock в класс, который наследует мультипроцессинг. Процесс - PullRequest
1 голос
/ 14 января 2020

Как я могу передать объект Lock в подкласс multiprocessing.Process? Я пробовал это, и я столкнулся с ошибкой засолки.

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()

Есть много ответов на вопросы о передаче блокировки на multiprocessing.Pool, но ни один из них не решил мою проблему с OOP подходом использования Process. Если я хочу сделать глобальную блокировку, где я должен определить ее и где я могу передать ее myProcess объектам?

1 Ответ

2 голосов
/ 14 января 2020

Вы не можете использовать threading.Lock для многопроцессорной обработки, вам нужно использовать multiprocessing.Lock.

Вы получаете ошибку засоления, потому что threading.Lock не может быть засолен, и вы находитесь на ОС, которая по умолчанию использует «spawn» для запуска новых процессов (Windows или macOS с Python 3.8 +).

Обратите внимание, что на разветвленной ОС (Linux, BSD ...), при использовании threading.Lock вы не получите ошибку травления, но блокировка будет реплицирована без предупреждения, не обеспечив синхронизацию между процессами , которые вы намеревались.

Использование отдельной функции для настройки блокировка возможна, но я бы предпочел передать ее в качестве аргумента Process.__init__() вместе с другими возможными аргументами.

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()

Вывод:

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

Process finished with exit code 0
...