cloudpickle
cloudpickle
使得序列化Python标准库中默认pickle
模块不支持的Python结构成为可能。
cloudpickle
对于集群计算特别有用,在这种情况下,Python代码通过网络传送到远程主机上执行,可能靠近数据所在位置。
除此之外,cloudpickle
还支持lambda函数以及在__main__
模块中交互定义的函数和类的序列化(例如在脚本、shell或Jupyter笔记本中)。
Cloudpickle只能用于在完全相同版本的Python之间传送对象。
不支持且强烈不建议使用cloudpickle
进行长期对象存储。
安全提示:应该只加载来自可信源的pickle数据,否则pickle.load
可能导致任意代码执行,造成严重的安全漏洞。
安装
cloudpickle
的最新版本可以从pypi获取:
pip install cloudpickle
示例
序列化lambda表达式:
>>> import cloudpickle
>>> squared = lambda x: x ** 2
>>> pickled_lambda = cloudpickle.dumps(squared)
>>> import pickle
>>> new_squared = pickle.loads(pickled_lambda)
>>> new_squared(2)
4
序列化在Python shell会话中交互定义的函数(在__main__
模块中):
>>> CONSTANT = 42
>>> def my_function(data: int) -> int:
... return data + CONSTANT
...
>>> pickled_function = cloudpickle.dumps(my_function)
>>> depickled_function = pickle.loads(pickled_function)
>>> depickled_function
<function __main__.my_function(data:int) -> int>
>>> depickled_function(43)
85
覆盖pickle对可导入结构的序列化机制:
cloudpickle
和pickle
之间一个重要的区别是,cloudpickle
可以按值序列化函数或类,而pickle
只能按引用序列化。按引用序列化将函数和类视为模块的属性,通过在加载时触发其模块导入的指令来序列化它们。因此,按引用序列化受限于假设反序列化环境中包含函数或类的模块可用/可导入。这一假设在序列化交互式会话中定义的结构时会失效,cloudpickle
会自动检测这种情况,并按值序列化这些结构。
另一种预期会打破可导入性假设的情况是在分布式执行环境中开发模块时:工作进程可能无法访问该模块,例如,如果它们位于与开发模块的进程不同的机器上。cloudpickle
本身无法检测这种"本地可导入"的模块并切换到按值序列化;相反,它依赖于默认模式,即按引用序列化。然而,从cloudpickle 2.0.0
版本开始,可以使用register_pickle_by_value(module)
/unregister_pickle_by_value(module)
API明确指定应该使用按值序列化的模块:
>>> import cloudpickle
>>> import my_module
>>> cloudpickle.register_pickle_by_value(my_module)
>>> cloudpickle.dumps(my_module.my_function) # my_function按值序列化
>>> cloudpickle.unregister_pickle_by_value(my_module)
>>> cloudpickle.dumps(my_module.my_function) # my_function按引用序列化
使用此API,无需在所有工作节点上重新安装新版本的模块,也无需重启工作进程:仅重启带有新源代码的客户端Python进程就足够了。
请注意,这个功能仍处于实验阶段,在以下情况下可能会失败:
-
如果按值序列化的函数/类的主体包含
import
语句:>>> def f(): >>> ... from another_module import g >>> ... # 如果反序列化环境中another_module不可用,调用f可能会失败 >>> ... return g() + 1
-
如果按引用序列化的函数在执行过程中使用了按值序列化的函数。
运行测试
-
使用
tox
,为所有支持的Python和PyPy版本运行测试:pip install tox tox
或者针对特定环境:
tox -e py312
-
使用
pytest
仅运行当前Python版本的测试:pip install -r dev-requirements.txt PYTHONPATH='.:tests' pytest
历史
cloudpickle
最初由picloud.com开发,作为客户端SDK的一部分。
cloudpickle.py
的副本被包含在PySpark中,即Apache Spark的Python接口。Davies Liu、Josh Rosen、Thom Neale和其他Apache Spark开发者对其进行了显著改进,特别是增加了对PyPy和Python 3的支持。
cloudpickle
项目的目标是将这项工作提供给Spark生态系统之外的更广泛受众,并通过专门的非回归测试套件使其更容易进一步改进。