3

Моего первоначального вопроса в том, что я пытаюсь сделать следующее:Невозможно рассортировать выражение Pyparsing с помощью метода setParseAction(). Необходимое для многопроцессорных

def submit_decoder_process(decoder, input_line): 
    decoder.process_line(input_line) 
    return decoder 

self.pool = Pool(processes=num_of_processes) 
self.pool.apply_async(submit_decoder_process, [decoder, input_line]).get() 

декодера усложнится, чтобы описать здесь, но главное в том, что декодер объект, который инициализируется с выражением Pyparsing который вызывает setParseAction(). Это не позволяет определить, что использует многопроцессорность, и это, в свою очередь, не позволяет выполнить вышеуказанный код.

Теперь вот проблема рассола/PyParsing, которую я выделил и упростил. В следующем коде появляется сообщение об ошибке из-за отказа рассола.

import pickle 
from pyparsing import * 

def my_pa_func(): 
    pass 

pickle.dumps(Word(nums).setParseAction(my_pa_func)) 

Сообщение об ошибке:

pickle.PicklingError: Can't pickle <function wrapper at 0x00000000026534A8>: it's not found as pyparsing.wrapper 

Теперь Если вы удалите .setParseAction вызова (my_pa_func), он будет работать без проблем:

pickle.dumps(Word(nums)) 

Как я могу обойти это? Многопроцессор использует рассол, поэтому я не могу этого избежать. Патсовый пакет, который предположительно использует укроп, недостаточно зрелый, по крайней мере, у меня возникают проблемы с его установкой на моем Windows-64bit. Я действительно царапаю голову здесь.

+0

~~ rant ~~: 'пафос' близок к 10-летнему ... с активным развитием почти все время (ну, периодически). Это тривиально устанавливается с помощью 'setuptools'. Он может быть установлен с помощью 'pip', если вы используете флаг' pre'. Я не вижу, как это не «зрелый» пакет ... кроме номера версии последнего стабильного выпуска (который * был * не проблемой до тех пор, пока стандарты номера версии не изменились). В любом случае, вздох. Ожидающий новый выпуск позаботится о проблемах с установкой 'pip' * чисто * из-за нумерации версий. –

ответ

5

ОК, вот решение вдохновлен rocksportrocker: Python multiprocessing pickling error

Идея заключается в том, чтобы укроп объект, который не может быть маринованный, проходя вперед и назад между процессами, а затем «undill» это после того, как это было прошло:

from multiprocessing import Pool 
import dill 

def submit_decoder_process(decoder_dill, input_line): 
    decoder = dill.loads(decoder_dill) # undill after it was passed to a pool process 
    decoder.process_line(input_line) 
    return dill.dumps(decoder) # dill before passing back to parent process 

self.pool = Pool(processes=num_of_processes) 

# Dill before sending to a pool process 
decoder_processed = dill.loads(self.pool.apply_async(submit_decoder_process, [dill.dumps(decoder), input_line]).get()) 
+0

Рад, что вы смогли это обработать, с помощью модуля 'dill'. В прошлом я вносил изменения в pyparsing для поддержки травления, но я никогда не пытался рассолить парсер с действиями синтаксического анализа - отличное решение, я посмотрю, есть ли способ включить его в pyparsing. – PaulMcG

0

https://docs.python.org/2/library/pickle.html#what-can-be-pickled-and-unpickled

multiprocessing.Pool использует протокол рассола для сериализации функции и модуля имен (в вашем примере setParseAction и pyparse), которые поставляются через трубы в дочерний процесс.

Детский процесс, после его получения, импортирует модуль и пытается вызвать функцию. Проблема в том, что то, что вы проходите, не является функцией, а методом. Чтобы решить эту проблему, протокол Pickle должен быть достаточно умен, чтобы создать объект «Word» с параметром «user», а затем вызвать метод setParseAction. Поскольку обработка этих случаев слишком сложна, протокол Pickle предотвращает сериализацию функций верхнего уровня.

Чтобы решить вашу проблему, вы проинструктируете модуль Pickle о том, как сериализовать метод setParseAction (https://docs.python.org/2/library/pickle.html#pickle-protocol), или вы реорганизуете свой код таким образом, чтобы переданное в Pool.apply_async сериализуемое.

Что делать, если вы передаете объект Word дочернему процессу, и вы позволите ему вызвать Word(). SetParseAction()?

0

Я предлагаю pathos.multiprocessing, как вы упомянули. Конечно, я автор pathos, поэтому я думаю, это не удивительно. Похоже, что может быть ошибка distutils, в которой вы работаете, как указано здесь: https://github.com/uqfoundation/pathos/issues/49.

Ваше решение с использованием dill является хорошим обходным решением.Вы также можете отказаться от установки всего пакета pathos и просто установить вилку pathos пакета multiprocessing (который использует dill вместо pickle). Вы можете найти его здесь: http://dev.danse.us/packages или здесь: https://github.com/uqfoundation/pathos/tree/master/external,

+0

Привет, Майк, это я открыл эту тему на github. Фактически, сначала я пытался использовать пафос, но поскольку он не устанавливался для меня по разным причинам, мне приходилось придумывать какое-то обходное решение. В любом случае, я с нетерпением жду использования пафоса, когда, надеюсь, все его проблемы будут решены. – jazzblue

+0

Да, я понял, что это вы. Я добавил выше для всех, кто сталкивается с той же ошибкой python, с которой вы столкнулись, поэтому у них также есть ссылка на ваш билет. В любом случае, нет хорошего активного кода, все его проблемы решены. :) Но я активно работаю над тем, чтобы пафос был проще установить. –

 Смежные вопросы

  • Нет связанных вопросов^_^