Модули multiprocessing_generator вызывают ошибку разрешения - PullRequest
0 голосов
/ 31 декабря 2018

Я нашел модуль multiprocessing_generator .Я попробовал этот модуль с кодом ниже:

from multiprocessing_generator import ParallelGenerator

def my_generator():
    yield (x*x for x in range(200))

with ParallelGenerator(my_generator(), max_lookahead=100) as g:
    for elem in g:
        print(elem)

Вот ошибка, которую я получил (я запустил мой код в консоли, файл python на моем рабочем столе):

C: \ Users \ crd \ Desktop> python test.py Traceback (последний вызов был последним): файл "test.py", строка 69, с ParallelGenerator (my_generator (), max_lookahead = 100) как g: File "C: \ Users \ crd \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ site-packages \ multiprocessing_generator__init __. Py ", строка 62, в введите файл self.process.start () ()" C: \ Users \ crd \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ multiprocessing \ process.py ", строка 112, в начале self._popen = self._Popen (self) Файл" C: \ Users \ crd\ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ multiprocessing \ context.py ", строка 223, в _Popen return _default_context.get_context (). Process._Popen (process_obj) Файл" C: \ Users \ crd \ AppData\ Local \ Programs \ Python \ Python37-32 \ lib \ multiprocessing \ context.py ", строка 322, в _Popen return Popen (process_obj) Файл" C: \ Users \ crd \ AppData \ Local\ Programs \ Python \ Python37-32 \ lib \ multiprocessing \ popen_spawn_win32.py ", строка 65, в init reduction.dump (process_obj, to_child) Файл" C: \ Users \ crd \ AppData \ Local \ "Программы \ Python \ Python37-32 \ lib \ multiprocessing \ redu.py ", строка 60, в дампе ForkingPickler (файл, протокол) .dump (obj) AttributeError: Невозможно выбрать локальный объект 'ParallelGenerator. init .. wrapped '

C: \ Users \ crd \ Desktop> Traceback (последний вызов был последним): файл "", строка 1, в файле "C: \ Users \ crd \ AppData \ Local \ Programs\ Python \ Python37-32 \ lib \ multiprocessing \ spawn.py ", строка 99, в spawn_main new_handle =uration.steal_handle (parent_pid, pipe_handle) Файл" C: \ Users \ crd \ AppData \ Local \ Programs \ Python \ Python37-32 \ lib \ multiprocessing \ redu.py ", строка 87, в steal_handle _winapi.DUPLICATE_SAME_ACCESS |_winapi.DUPLICATE_CLOSE_SOURCE) PermissionError: [WinError 5] Accès refusé

Я очистил код из модуля multiprocessing_generator (я удалял все попытки / исключения, я преобразовывал менеджер контекста в базовую функцию).Но с кодом ниже я получил ту же ошибку:

from queue import Empty

from multiprocessing import Process, Queue

def ParallelGeneratorLight():
    queue = Queue()

    def wrapped():
        for item in (x*x for x in range(200)):
            queue.put(item)

    process = Process(target=wrapped)

    process.start()
    queue.get()

print(ParallelGeneratorLight())

Что с этим не так?

1 Ответ

0 голосов
/ 02 января 2019

multiprocessing_generator опирается на многопроцессорный модуль, использующий метод запуска 'fork', поскольку предполагается, что вложенная функция wrapped (определенная в ParallelGenerator __init__) может быть передана как targetmultiprocessing.Process объект.На платформе fork это нормально;дочерний процесс наследует полное состояние родительского объекта (с несколькими небольшими исключениями, такими как потоки), поэтому он имеет равный доступ к вложенной функции wrapped (в конце концов, он унаследовал точную копию).

Проблема в том, чтов Windows единственным доступным методом запуска является 'spawn', для которого требуется, чтобы target (и все аргументы) были в состоянии pickle (он их pickle отправляет, потомку через IPC и восстанавливает ихтам), а вложенные функции никогда не могут pickle (pickle, когда функция включает выбор своего квалифицированного имени для импорта и использования на другой стороне, а квалифицированное имя вложенной функции включает не импортируемые компоненты, в этом случае,pickle ing ParallelGenerator.__init__.<locals>.wrapped завершается ошибкой, поскольку <locals> явно не является импортируемым именем).

По сути, multiprocessing_generator работает только в UNIX-подобных системах и только если вы используете метод запуска по умолчанию('fork');если вы вызвали set_start_method с каким-либо другим значением ('forkserver' или 'spawn'), multiprocessing_generator не сможет работать.

Хотя это ошибка, этоне особенно критическая ошибка в большинстве случаев;у модуля очень мало пользы, если в генераторе должны быть выбраны значения, потому что большинство таких генераторов либо не pickle способны (например, большинство файловоподобных объектов), либо pickle требует их запуска до завершения (в этом случае вы потеряли весь свой параллелизм).

Извините, но простой ответ здесь: Не используйте multiprocessing_generator в Windows.

Этосказал, что если ваш генератор связан с вводом / выводом, вы можете извлечь выгоду из модуля, импортировав его, а затем сразу же исправьте его, чтобы заменить все multiprocessing компоненты, на которые он полагается, их эквивалентамиmultiprocessing.dummy имен (которые опираются на потоки и не полагаются на травление), например,

from multiprocessing_generator import ParallelGenerator
import multiprocessing.dummy, multiprocessing_generator

# Monkey-patch to use threads
multiprocessing_generator.Process = multiprocessing.dummy.Process
multiprocessing_generator.Queue = multiprocessing.dummy.Queue

Чтобы было ясно, я не проверял это;никаких гарантий не выражено или подразумевается относительно того, будет ли это работать.Также будет совершенно бессмысленно, если генератор привязан к процессору, по крайней мере, на эталонном интерпретаторе CPython, поскольку генераторы, привязанные к процессору, будут удерживать GIL во время работы, не давая основному потоку выполнять работу, поэтомус таким же успехом мог бы повторяться напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...