cloudpickle:让 Python 对象随意穿越进程边界
cloudpickle:让 Python 对象随意穿越进程边界
cloudpickle 在 GitHub 上已积累 1,927 颗 Star,由 cloudpipe 组织维护。它的作用很直接:扩展 Python 标准库里的 pickle,让那些在常规序列化场景下会报错的代码对象也能被打包带走。

1、 这玩意儿是干嘛的
Python 自带的 pickle 模块有个边界:它只能序列化那些可以被「引用还原」的对象。lambda 表达式、在交互式环境里定义的函数和类、main 模块里的临时代码,这些 pickle 都认不出来。
cloudpickle 把这些缺口补上了。它能按「值」而不是「引用」去序列化函数和类,把这些对象的代码体一并打包。解压的时候,不需要原模块存在,代码本身就能重建。
这个特性在集群计算里几乎是刚需。远程节点上跑的任务,经常要把本地的 Python 函数传过去执行。用 pickle 传不过去的东西,cloudpickle 能传。
cloudpickle 最早由 PiCloud 开发并作为其客户端 SDK 的一部分发布。后来 PySpark 直接内置了 cloudpickle.py 的副本,Davies Liu 等 Apache Spark 开发者对其进行了大幅改进,加入了对 PyPy 和 Python 3 的支持。现在这个独立项目的目标,是把这份成果从 Spark 生态里剥离出来,服务更广泛的 Python 开发者,并通过一套专用的回归测试套件持续迭代。

2、 它具体能序列化什么
标准 pickle 的工作方式是把函数和类当成模块的属性,序列化时只记录模块名和属性名,反序列化时再通过 import 还原。这个机制在普通场景下没问题,但一旦遇到交互式会话、动态生成的代码、或者分布式环境里模块文件不在目标节点上的情况,就会直接失效。
cloudpickle 的核心能力覆盖这几个场景:
- lambda 函数:普通的 pickle 遇到 lambda 直接抛异常,cloudpickle 可以正常处理
- 交互式定义的函数和类:IPython、Jupyter Notebook、Python shell 里随手写的代码都能打包
- 嵌套函数和闭包:捕获了外部变量的内部函数也能完整序列化
- 带类型注解的函数:PEP 484 注解信息不会丢失
安装只需要一行:
pip install cloudpickle
基础用法和 pickle 保持一致:
import cloudpickle
squared = lambda x: x ** 2
pickled = cloudpickle.dumps(squared)
import pickle
new_squared = pickle.loads(pickled)
new_squared(2) # 4
交互式会话里定义的函数也一样:
CONSTANT = 42
def my_function(data: int) -> int:
return data + CONSTANT
pickled_function = cloudpickle.dumps(my_function)
restored = pickle.loads(pickled_function)
restored(43) # 85
3、 by value 和 by reference 的切换
cloudpickle 默认对可导入的模块使用 by reference 序列化,对交互式代码自动切到 by value。从 2.0.0 开始,你可以手动指定某个模块强制走 by value:
import cloudpickle
import my_module
cloudpickle.register_pickle_by_value(my_module)
cloudpickle.dumps(my_module.my_function) # 按值序列化
cloudpickle.unregister_pickle_by_value(my_module)
cloudpickle.dumps(my_module.my_function) # 恢复按引用
这意味着开发阶段改了代码,不需要重新部署到所有工作节点,重启客户端进程就够了。
这个功能目前还在实验阶段,有两个已知限制:函数体里如果直接 import 了其他模块,目标环境没有的话会报错;by reference 的函数调用 by value 的函数时,也可能出问题。
4、 适合哪些人用
- 用 Dask、Ray、PySpark 做分布式计算的开发者,要把本地函数分发到远程节点
- 在 Jupyter 里做交互式开发,需要把 notebook 里的函数持久化或传递的人
- 写并行任务调度框架的库作者,需要比 pickle 更宽泛的序列化能力
有一点需要明确:cloudpickle 只支持相同 Python 版本之间的传输,跨版本直接不可用。它也不建议用来做长期对象存储,因为序列化格式并不保证向后兼容。
和 pickle 一样,加载来源不明的数据有安全风险。cloudpickle.loads 可以触发任意代码执行,所以只应该在可信环境下使用,不要拿它来反序列化从网络接收的未经验证的数据。
浙公网安备 33010602011771号