为什么要使用 marshal 转储和 pickle 加载?
Why to use marshal to dump and pickle to load?
我正在尝试了解 python2 库 remotely,它有助于通过 xmlrpc 远程 运行 编码。
在客户端,作者使用 marshal 转储对象,并使用 pickle 加载从服务器发回的结果:
def run(self, func, *args, **kwds):
code_str = base64.b64encode(marshal.dumps(func.func_code))
output = self.proxy.run(self.api_key, self.a_sync, code_str, *args, **kwds)
return pickle.loads(base64.b64decode(output))
而在服务器端,他正在做相反的事情:
def run(self, api_key, a_sync, func_str, *args, **kwds):
#... truncated code
code = marshal.loads(base64.b64decode(func_str))
func = types.FunctionType(code, globals(), "remote_func")
#... truncated code
output = func(*args, **kwds)
output = base64.b64encode(pickle.dumps(output))
return output
用 marshal 转储并用 pickle 加载结果的目的是什么? (反之亦然)
首先使用 marshal
发送的对象属于非常特殊的类型。它是一个代码对象,只需要支持该类型。这是 marshal
模块旨在处理的类型。另一方面,return 值可以是任何类型,它由 func
函数 return 的内容决定。 pickle
模块有一个更通用的协议,可以序列化许多不同类型的对象,因此它很有可能支持 return 值。
虽然您可以对在程序之间传递的两个数据项使用 pickle
,但 marshal
模块的输出对于传递代码对象来说更加紧凑和高效,因为 pickle
只是环绕它。如果您尝试使用 marshal
和 pickle
转储相同的代码对象(使用协议零,Python 2 中的默认协议),您将在内部看到 marshal
的输出pickle
!
的输出
所以总结一下,使用marshal
模块发送代码,因为只需要发送个代码对象,而且是低级序列化,可以有时效率更高一点。 return 值使用 pickle
发回,因为程序无法预测它将是什么类型的对象,并且 pickle
可以序列化比 marshal
更复杂的值,以一些额外的复杂性和(有时)序列化的大小为代价。
我正在尝试了解 python2 库 remotely,它有助于通过 xmlrpc 远程 运行 编码。
在客户端,作者使用 marshal 转储对象,并使用 pickle 加载从服务器发回的结果:
def run(self, func, *args, **kwds):
code_str = base64.b64encode(marshal.dumps(func.func_code))
output = self.proxy.run(self.api_key, self.a_sync, code_str, *args, **kwds)
return pickle.loads(base64.b64decode(output))
而在服务器端,他正在做相反的事情:
def run(self, api_key, a_sync, func_str, *args, **kwds):
#... truncated code
code = marshal.loads(base64.b64decode(func_str))
func = types.FunctionType(code, globals(), "remote_func")
#... truncated code
output = func(*args, **kwds)
output = base64.b64encode(pickle.dumps(output))
return output
用 marshal 转储并用 pickle 加载结果的目的是什么? (反之亦然)
首先使用 marshal
发送的对象属于非常特殊的类型。它是一个代码对象,只需要支持该类型。这是 marshal
模块旨在处理的类型。另一方面,return 值可以是任何类型,它由 func
函数 return 的内容决定。 pickle
模块有一个更通用的协议,可以序列化许多不同类型的对象,因此它很有可能支持 return 值。
虽然您可以对在程序之间传递的两个数据项使用 pickle
,但 marshal
模块的输出对于传递代码对象来说更加紧凑和高效,因为 pickle
只是环绕它。如果您尝试使用 marshal
和 pickle
转储相同的代码对象(使用协议零,Python 2 中的默认协议),您将在内部看到 marshal
的输出pickle
!
所以总结一下,使用marshal
模块发送代码,因为只需要发送个代码对象,而且是低级序列化,可以有时效率更高一点。 return 值使用 pickle
发回,因为程序无法预测它将是什么类型的对象,并且 pickle
可以序列化比 marshal
更复杂的值,以一些额外的复杂性和(有时)序列化的大小为代价。