Почему многопроцессорная сериализация с травлением зависит от области применения? - PullRequest
0 голосов
/ 12 ноября 2019

Я пытаюсь понять, как параллелизм работает в общем и, в данном случае, как он работает конкретно в Python.

Я уже некоторое время использую библиотеку inputs и всегда должен был"cheat" при порождении процессов, использующих его - выполнить скрипт с subprocess.Popen. Сегодня я, не задумываясь, поместил одну строку кода в другое место и сумел успешно создать целевую функцию Process. Но я не понимаю, почему это работает ...

Следующий код предоставляет два простых класса: один содержит ссылку на controller в self , а другой - нет(и использует глобальную ссылку, объявленную в модуле):

import inputs
import multiprocessing
import time

controller = inputs.devices.gamepads[0]


class TestBroken:

    def __init__(self):
        self.controller = controller

    def read(self):
        while True:
            ev = self.controller.read()[0]
            print(ev.code, ev.state)


class TestWorking:

    def read(self):
        while True:
            ev = controller.read()[0]
            print(ev.code, ev.state)


if __name__ == '__main__':
    t = TestWorking()
    # Uncomment the line below to get the errors
    #t = TestBroken()
    multiprocessing.Process(target=t.read).start()
    while True:
        print("I'm alive!")
        time.sleep(1)

Ошибка после раскомментирования #t = TestBroken() выглядит следующим образом:

Traceback (most recent call last):
  File "C:/Coding/...", line 31, in <module>
    multiprocessing.Process(target=t.read).start()
  File "C:\Python\lib\multiprocessing\process.py", line 121, in start
    self._popen = self._Popen(self)
  File "C:\Python\lib\multiprocessing\context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Python\lib\multiprocessing\context.py", line 326, in _Popen
    return Popen(process_obj)
  File "C:\Python\lib\multiprocessing\popen_spawn_win32.py", line 93, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Python\lib\multiprocessing\reduction.py", line 60, in dump
    ForkingPickler(file, protocol).dump(obj)
AttributeError: Can't pickle local object 'CDLL.__init__.<locals>._FuncPtr'

Я не совсем понимаю, как хранитьссылка на объект заставляет pickle сходить с ума, в то время как сохранение той же ссылки на уровне модуля разрешено. Я прошу вашей помощи, чтобы раскрыть тайны, стоящие за этой проблемой.

...