繁体   English   中英

将python多重处理与类函数一起使用时出现酸洗错误

[英]Pickling error when using python multiprocessing with class functions

我有三个脚本, scheduler.py是基于multiprocessing.Processmultiprocessing.Pipe的并行任务运行multiprocessing.Pipe ,第二个脚本是simulation.pyx ,这是一个脚本,其中包含一些我想通过scheduler.py并行执行的类和函数scheduler.py ,最后是一个小的主脚本,在该脚本中,我从scheduler.py创建并行化类的实例,将其传递给simulation.pyx的类,然后运行整个程序。

当目标并行函数位于simulation.pyx的顶层时,一切正常,但是,一旦我尝试将scheduler.pysimulation.pyx的类函数一起使用,就会出现酸洗错误。

由于代码是几千行,所以我只给出一些概念性代码:

small_main_script.py

import simulation
import scheduler


if __name__ == '__main__':

    main = simulation.Main()
    scheduler = scheduler.parallel()
    main.simulate(scheduler)



simulation.pyx

import scheduler

cdef do_something_with_job(job):
...

cdef class Main:
    cdef public ...
    ...

    def __init__(self):
    ...

    def some_function(self,job):
        ...
        do_something_with_job(job)
        ...

    def simulate(self, scheduler):

        for job in job_list:
            scheduler.add_jobs(job)

        scheduler.target_function = self.some_function

        scheduler.run_in_parallel()

问题是,如果我使用像

def sleep(job):
    time.sleep(2)

并将其放在顶层,即在类外部,并行化工作正常,但是一旦我将其放入Main类中,我就会出现一个酸洗错误。 如果我使用在Main类中定义的真实目标函数,也不想将其移到顶层,则会遇到相同的错误。 以下是当我在Main类中使用伪函数sleep(self,job)时发生的情况。 当它不在课堂上时,它可以正常工作。

PicklingError: Can't pickle <built-in method sleep of simulation.Main
object at 0x0D4A3C00>: it's not found as __main__.sleep

In [2]: Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Python27\lib\multiprocessing\forking.py", line 381, in main self = load(from_parent)
  File "C:\Python27\lib\pickle.py", line 1384, in load return Unpickler(file).load()
  File "C:\Python27\lib\pickle.py", line 864, in load dispatch[key](self)
  File "C:\Python27\lib\pickle.py", line 886, in load_eof

    raise EOFError
EOFError

我正在使用Python 2.7

更新

我设法进一步隔离了问题。 当使用第三方软件包pathos multiprocessing我可以腌制类函数。 现在的问题似乎是在使用作为类实例的函数参数时出现错误。

根据Python多处理编程指南

可腌制性:确保代理方法的参数可腌制。

只有顶级功能picklable

很难腌制非顶级函数(类/实例方法,嵌套函数等)的原因是因为很难在子进程中以可移植的方式查找它们。 您正在发送实例方法以执行的进程可能对拥有该方法本身的对象一无所知。

如编程准则所建议:

但是,通常应该避免使用管道或队列将共享对象发送到其他进程。 相反,您应该安排程序,以便需要访问在其他位置创建的共享资源的进程可以从祖先进程继承该程序。

换句话说,创建一个将方法传递给目标关键字的过程。

Pathos库扩展了pickle协议,允许序列化比标准协议支持的更多类型。

通常,不建议将OOP与多处理程序混合使用,因为存在一些可能会引起误解的特殊情况。 这就是其中之一。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM