将python多处理与类函数

时间:2016-11-16 09:43:37

标签: python python-2.7 multiprocessing python-multiprocessing pathos

我有三个脚本scheduler.py,它是基于multiprocessing.Processmultiprocessing.Pipe的并行任务运行器,第二个脚本是simulation.pyx,它是一个包含某些类的脚本和我希望通过scheduler.py并行执行的函数,最后是一个小主脚本,我从scheduler.py创建并行化类的实例,将其传递给simulation.pyx中的类并运行整件事。

当目标并行函数位于simulation.pyx的顶层时,一切正常,但是当我尝试在scheduler.py中使用simulation.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中定义的真实目标函数并且我不想将其移动到顶层,我会得到相同的错误。以下是在类sleep(self,job)中使用虚函数Main时会发生的情况。当它在课外时它工作正常。

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时,我能够挑选类功能。现在的问题似乎是在使用类实例的函数参数时出现错误。

1 个答案:

答案 0 :(得分:0)

来自Python多处理programming guidelines

  

可分离性:确保代理方法的参数是可选择的。

只有顶级功能picklable

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

正如编程指南所示:

  

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

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

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

一般情况下,不建议混合使用OOP和多处理,因为有几个极端情况可能会产生误导。这是其中之一。