有没有简单的方法来腌制一个Python函数(或以其他方式序列化其代码)?
我试图通过networking连接(使用asyncore)传输一个函数。 是否有一个简单的方法来序列化一个Python函数(至less在这种情况下,将不会有副作用)的传输?
我最好喜欢有一对类似于这些function:
def transmit(func): obj = pickle.dumps(func) [send obj across the network] def receive(): [receive obj from the network] func = pickle.loads(s) func()
您可以将函数字节码序列化,然后在调用者上重新构build它。 编组模块可以用来序列化代码对象,然后可以重新组装成一个函数。 即:
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
几点注意事项:
-
元帅的格式(任何python字节码)在主要的python版本之间可能不兼容。
-
将只适用于cpython实现。
-
如果函数引用全局variables(包括导入的模块,其他函数等),则需要将它们串行化,或者在远程端重新创build它们。 我的例子只是给它的远程进程的全局命名空间。
-
您可能需要做更多的工作来支持更复杂的情况,如closures或发电机function。
查看Dill ,它扩展了Python的pickle库以支持更多种类的types,包括函数:
>>> 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模块 ),它返回一个String和一个函数或方法的源代码。
这完全取决于你是否在运行时生成函数:
如果你这样做 – inspect.getsource(object)
将不能用于dynamic生成的函数,因为它从.py
文件获取对象的源,所以只有在执行前定义的函数才能作为源检索。
如果你的函数放在文件中,为什么不让接收者访问它们,只传递模块和函数的名字。
我能想到的dynamic创build函数的唯一解决scheme是在传输之前将函数构build为string,然后在接收端对其进行传输,然后进行eval()
。
编辑: marshal
解决scheme看起来也很聪明,不知道你可以序列化其他内置的东西
cloud
包(pip安装云)可以腌制任意代码,包括依赖关系。 请参阅https://stackoverflow.com/a/16891169/1264797 。
这个模块使用的基本function涵盖了你的查询,加上你得到最好的电线压缩; 看到指导性的源代码:
y_serial.py模块::使用SQLite仓库Python对象
“Serialization + persistance ::在几行代码中,将Python对象压缩并注释到SQLite中,然后在没有任何SQL的情况下按关键字按时间顺序检索它们,这是数据库存储无模式数据最有用的”标准“模块。