不能使用setParseAction()方法来pickle Pyparsing表达式.需要多处理

jaz*_*lue 3 python pickle pyparsing python-multithreading python-multiprocessing

我的原始问题是我正在尝试执行以下操作:

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()
Run Code Online (Sandbox Code Playgroud)

解码器在这里有点介绍,但重要的是解码器是一个用调用setParseAction()的PyParsing表达式初始化的对象.这会使多处理使用的pickle失败,这反过来又失败了上面的代码.

现在,这是我已经孤立和简化的pickle/PyParsing问题.由于pickle失败,以下代码会产生错误消息.

import pickle
from pyparsing import *

def my_pa_func():
    pass

pickle.dumps(Word(nums).setParseAction(my_pa_func))
Run Code Online (Sandbox Code Playgroud)

错误信息:

pickle.PicklingError: Can't pickle <function wrapper at 0x00000000026534A8>: it's not found as pyparsing.wrapper
Run Code Online (Sandbox Code Playgroud)

现在,如果你删除调用.setParseAction(my_pa_func),它将没有问题:

pickle.dumps(Word(nums))
Run Code Online (Sandbox Code Playgroud)

我怎么能绕过它呢?多处理使用泡菜,所以我猜不出它.据说使用dill的pathos包不够成熟,至少,我在Windows-64bit上安装它时遇到问题.我真的在这里摸不着头脑.

jaz*_*lue 5

好的,这是受Rocksportrocker启发的解决方案:Python多处理酸洗错误

我们的想法是在进程之间来回传递不能被腌制的对象,然后在传递之后"解除"它:

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())
Run Code Online (Sandbox Code Playgroud)