一尘不染

Python多处理PicklingError:无法pickle<type'function'>

python

我不能用一个简单的例子再现这个错误,而且我的代码太复杂了,无法发布。如果我用I Python shell而不是普通的Python来运行程序,事情会很顺利。
我查阅了以前关于这个问题的一些笔记。它们都是由使用池调用类函数中定义的函数引起的。但对我来说不是这样。

Exception in thread Thread-3:
Traceback (most recent call last):
  File "/usr/lib64/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib64/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib64/python2.7/multiprocessing/pool.py", line 313, in _handle_tasks
    put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

我很感激你的帮助。
更新:函数I pickle是在模块的顶层定义的。尽管它调用包含嵌套函数的函数。i、 e,f()调用g()调用h()h()有一个嵌套函数i(),我正在调用pool.apply_async(f)f()g()h()都是在顶层定义的。我用这个模式尝试了一个更简单的例子,但还是成功了。


阅读 1076

收藏
2020-02-14

共1个答案

一尘不染

这是一份可以腌制的东西的清单。特别是,函数只有在模块的顶层定义时才是可选择的。
这段代码:

import multiprocessing as mp

class Foo():
    @staticmethod
    def work(self):
        pass

if __name__ == '__main__':   
    pool = mp.Pool()
    foo = Foo()
    pool.apply_async(foo.work)
    pool.close()
    pool.join()

产生的错误几乎与你发布的错误相同:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 315, in _handle_tasks
    put(task)
PicklingError: Can't pickle <type 'function'>: attribute lookup __builtin__.function failed

问题在于,pool所有方法都使用a mp.SimpleQueue将任务传递给工作进程。mp.SimpleQueue必须经过的所有内容都必须是可选取的,并且foo.work不可选取,因为它不是在模块的顶层定义的。

可以通过在顶层定义一个函数来修复该问题,该函数调用foo.work()

def work(foo):
    foo.work()

pool.apply_async(work,args=(foo,))

请注意,它foo是可拾取的,因为它Foo是在顶层定义的并且 foo.__dict__是可拾取的。

2020-02-14