ネットワーク接続を介して機能を転送しようとしています(非同期機能を使用)。このような転送のためにpython関数(この場合は少なくともこの場合、副作用はありません)をシリアル化する簡単な方法はありますか?
理想的には、次のような機能のペアが必要です。
def transmit(func):
obj = pickle.dumps(func)
[send obj across the network]
def receive():
[receive obj from the network]
func = pickle.loads(s)
func()
関数バイトコードをシリアル化し、呼び出し元で再構築できます。 marshal モジュールを使用してコードオブジェクトをシリアル化し、それを関数に再アセンブルできます。すなわち:
import marshal
def foo(x): return x*x
code_string = marshal.dumps(foo.func_code)
次に、リモートプロセスで(code_stringを転送した後):
import marshal, types
code = marshal.loads(code_string)
func = types.FunctionType(code, globals(), "some_func_name")
func(10) # gives 100
いくつかの注意事項:
marshalの形式(任意のpythonバイトコード)は、メジャーpythonバージョン間で互換性がない場合があります。
Cpython実装でのみ機能します。
関数がピックアップする必要があるグローバル(インポートされたモジュール、他の関数などを含む)を参照する場合、これらもシリアル化するか、リモート側で再作成する必要があります。私の例では、リモートプロセスのグローバル名前空間を指定しています。
クロージャーやジェネレーター関数などのより複雑なケースをサポートするには、おそらくもう少し行う必要があります。
Dill を確認してください。これは、Pythonのpickleライブラリを拡張して、関数を含むより多くのタイプをサポートします。
>>> import dill as pickle
>>> def f(x): return x + 1
...
>>> g = pickle.dumps(f)
>>> f(1)
2
>>> pickle.loads(g)(1)
2
また、関数のクロージャー内のオブジェクトへの参照もサポートしています。
>>> def plusTwo(x): return f(f(x))
...
>>> pickle.loads(pickle.dumps(plusTwo))(1)
3
Pyro は これをあなたのために にできます。
最も簡単な方法は、おそらくinspect.getsource(object)
( inspect module を参照)であり、関数またはメソッドのソースコードを含むStringを返します。
それはすべて、実行時に関数を生成するかどうかに依存します。
実行すると、inspect.getsource(object)
は_.py
_ファイルからオブジェクトのソースを取得するため、動的に生成された関数では機能しません。したがって、実行前に定義された関数のみがソースとして取得できます。
とにかく関数がファイルに配置されている場合、レシーバーにそれらへのアクセスを許可せず、モジュールと関数名のみを渡すようにしてください。
私が考えることができる動的に作成された関数の唯一の解決策は、送信前に関数を文字列として構築し、ソースを送信し、次に受信側でeval()
します。
編集:marshal
ソリューションも非常にスマートに見えますが、組み込みのその他の何かをシリアル化できることを知りませんでした
cloud
パッケージ(pip install cloud)は、依存関係を含む任意のコードをpickleできます。 https://stackoverflow.com/a/16891169/1264797 を参照してください。
code_string = '' ' def foo(x): return x * 2 def bar(x): return x ** 2 '' ' obj = pickle.dumps(code_string)
いま
exec(pickle.loads(obj)) foo(1) > 2 bar(3) > 9
このモジュールで使用される基本的な機能はクエリをカバーし、さらに回線を介して最高の圧縮を実現します。有益なソースコードを参照してください。
y_serial.pyモジュール:: warehouse Python SQLiteのオブジェクト
「シリアル化+永続化::数行のコードで、PythonオブジェクトをSQLiteに圧縮して注釈を付けます。その後、SQLを使用せずにキーワードで時系列にそれらを取得します。スキーマレスデータを保存します。」