1. ホーム
  2. パイソン

[解決済み】Pythonマルチプロセッシング PicklingError: <type 'function'> をピクルスにできない。

2022-03-27 10:58:03

質問

もっと簡単な例でエラーを再現することができず、また私のコードが複雑すぎて掲載できないのが残念です。通常のPythonの代わりにIPythonのシェルでプログラムを実行するとうまくいきます。

この問題についての過去のメモを調べてみました。それらはすべて、クラス関数内で定義された関数を呼び出すためにプールを使用することが原因でした。しかし、これは私の場合ではありません。

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

ご協力をお願いします。

更新情報 : 私がpickleした関数は、モジュールのトップレベルで定義されています。しかし、それはネストされた関数を含む関数を呼び出します。 f() が呼び出す g() コール h() これは、ネストされた関数 i() を呼び出しています。 pool.apply_async(f) . f() , g() , h() はすべてトップレベルで定義されています。このパターンでもっと簡単な例を試してみましたが、うまくいきました。

解決方法は?

ここで 漬けられるものリスト . 特に、関数はモジュールのトップレベルで定義されている場合のみ pickl 可能です。

このコード片は

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 メソッドはすべて mp.SimpleQueue を使用してワーカープロセスにタスクを渡します。を経由するものはすべて mp.SimpleQueue はピッキング可能でなければならず foo.work は、モジュールのトップレベルで定義されていないため、picklableではありません。

この問題は、トップレベルで関数を定義し、その関数が foo.work() :

def work(foo):
    foo.work()

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

注目すべきは foo はピッキング可能です。 Foo はトップレベルで定義され foo.__dict__ はピックル可能です。