9

ピクルされた関数/クラスが __main__ 名前空間にあり、別のスクリプト/モジュールでのピクル解除が失敗するという明らかな問題 (他の投稿で言及) を使用して、__main__ 内から関数またはクラスをピクルできるようにしたいと考えています。

機能する次の解決策がありますが、これを行うべきではない理由はありますか?

以下は myscript.py にあります。

import myscript
import pickle

if __name__ == "__main__":               

    print pickle.dumps(myscript.myclass())

else:

    class myclass:
        pass

edit : unpickle は、myscript.pyにアクセスできるimport myscriptスクリプト/モジュールで行われ、 . 目的は、並列 pythonのようなソリューションを使用して関数をリモートで呼び出し、リモートでアクセスできる関数/クラスを含む短いスタンドアロンスクリプトを記述できるようにすることです。

4

3 に答える 3

3

をインポートし__main__、そのモジュールで使用可能なメソッドを使用することで、グローバル オブジェクトをより適切に処理できます。これは、Python でほとんどすべてのものをシリアライズするためにdillが行うことです。基本的に、dill が対話的に定義された関数をシリアライズする場合、有効なモジュール__main__を作成するシリアライゼーション側とデシリアライゼーション側の両方で名前マングリングを使用します。__main__

>>> import dill
>>> 
>>> def bar(x):
...   return foo(x) + x
... 
>>> def foo(x):
...   return x**2
... 
>>> bar(3)
12
>>> 
>>> _bar = dill.loads(dill.dumps(bar))
>>> _bar(3)
12

実際、dill はその型をpickleレジストリに登録するため、使用するブラック ボックス コードがpickleあり、実際には編集できない場合は、dill をインポートするだけで、サード パーティのコードにモンキーパッチを適用しなくても、魔法のように動作させることができます。

または、インタープリター セッション全体を「python イメージ」として送信したい場合は、dill もそれを行うことができます。

>>> # continuing from above
>>> dill.dump_session('foobar.pkl')
>>>
>>> ^D
dude@sakurai>$ python
Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
[GCC 4.2.1 (Apple Inc. build 5566)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('foobar.pkl')
>>> _bar(3)
12

pickle のバージョン互換性があり、python の変更やインストールに関する通常の注意事項がある限り、イメージを ssh 経由で別のコンピューターに簡単に送信し、中断したところから開始することができます。

私は実際に dill を使用してオブジェクトをシリアル化し、並列 python、 multiprocessing 、およびmpi4pyを使用して並列リソースに送信します。これらを便利にpathosパッケージ (およびMPI の場合はpyinamap ) にまとめます。これにより、さまざまな並列バッチ処理バックエンドに統一されたインターフェイスが提供されます。

>>> # continued from above
>>> from pathos.multiprocessing import ProcessingPool as Pool
>>> Pool(4).map(foo, range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>
>>> from pyina.launchers import MpiPool
>>> MpiPool(4).map(foo, range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

ノンブロッキングおよび反復マップ、非並列パイプ接続もあります。用の pathos モジュールもありますが、ppで定義されている関数についてはやや不安定です__main__。その改善に取り組んでいます。必要に応じて、github でコードをフォークし、ppで定義されている関数の改善にご協力ください__main__ppピクルスがうまくいかない理由はpp、一時ファイルオブジェクトを使用してインタープリターセッションの履歴を読み取ることによるシリアル化のトリックです...したがって、マルチプロセッシングやmpi4pyと同じ方法でオブジェクトをシリアル化しません。dill.source使用するのと同じタイプの酸洗をシームレスに行うディルモジュールがありますがpp、それはかなり新しいものです。

于 2013-10-17T13:56:41.437 に答える
1

とは別の場所で使用できるように何かをピクルしようとしている場合test_script、ピクルは(明らかに)モジュールから関数をロードしようとするだけなので、うまくいきません。次に例を示します。

test_script.py

def my_awesome_function(x, y, z):
    return x + y + z

picklescript.py

import pickle
import test_script
with open("awesome.pickle", "wb") as f:
    pickle.dump(test_script.my_awesome_function, f)

を実行python picklescript.pyして のファイル名を変更するtest_scriptと、関数をロードしようとすると失敗します。例えば

これを実行する:

import pickle
with open("awesome.pickle", "rb") as f:
    pickle.load(f)

次のトレースバックが表示されます。

Traceback (most recent call last):
  File "load_pickle.py", line 3, in <module>
    pickle.load(f)
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/pickle.py", line 1378, in load
    return Unpickler(file).load()
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/pickle.py", line 1090, in load_global
    klass = self.find_class(module, name)
  File "/Library/Frameworks/Python.framework/Versions/7.3/lib/python2.7/pickle.py", line 1124, in find_class
    __import__(module)
ImportError: No module named test_script
于 2012-08-08T15:07:11.147 に答える