1. ホーム
  2. python

[解決済み] Pythonの関数をpickleする(あるいはそのコードをシリアライズする)簡単な方法はありますか?

2022-07-25 20:01:35

質問

私はネットワーク接続を介して関数を転送しようとしています(asyncoreを使用して)。このような転送のために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()

どのように解決するのですか?

関数のバイトコードをシリアライズし、呼び出し側で再構築することができます。 その際 マーシャル モジュールを使ってコードオブジェクトをシリアライズし、それを関数に再構築することができます。

import marshal
def foo(x): return x*x
code_string = marshal.dumps(foo.__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の実装のためにのみ動作します。

  • もし関数がグローバル(インポートされたモジュール、他の関数などを含む)を参照し、それを拾う必要がある場合は、それらもシリアライズするか、リモート側で再作成する必要があります。 私の例では、リモート プロセスのグローバル名前空間を与えるだけです。

  • クロージャやジェネレータ関数のような、より複雑なケースをサポートするために、おそらくもう少し工夫が必要でしょう。