有没有简单的方法来腌制一个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的情况下按关键字按时间顺序检索它们,这是数据库存储无模式数据最有用的”标准“模块。

http://yserial.sourceforge.net