有没有一种简单的方法来pickle一个python函数(或者序列化它的代码)?

2024-05-15 00:57:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试通过网络连接(使用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()

Tags: the方法函数obj序列化def情况network
3条回答

您可以序列化函数字节码,然后在调用者上重新构造它。可以使用marshal模块序列化代码对象,然后将其重新组合为函数。即:

import marshal
def foo(x): return x*x
code_string = marshal.dumps(foo.func_code)

然后在远程进程中(传输代码字符串后):

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

相关问题 更多 >

    热门问题