有没有简单的方法将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()
12 个回答
13
最简单的方法可能就是用 inspect.getsource(object)
这个命令(可以查看 inspect模块 的相关内容),它会返回一个字符串,里面包含了某个函数或方法的源代码。
61
看看这个 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
147
你可以把函数的字节码进行序列化,然后在调用者那边再重建它。可以使用marshal模块来序列化代码对象,这样就能把它们重新组装成一个函数。比如:
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实现。
如果函数引用了全局变量(包括导入的模块、其他函数等),你需要把这些也序列化,或者在远程端重新创建它们。我的例子只是给了远程进程的全局命名空间。
如果要支持更复杂的情况,比如闭包或生成器函数,可能还需要做更多的工作。