0

0

Python怎么序列化一个对象(pickle)_pickle模块对象序列化与反序列化

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-09-12 14:02:01

|

350人浏览过

|

来源于php中文网

原创

pickle模块用于Python对象的序列化与反序列化,支持复杂对象类型,但仅限于可信环境使用,因反序列化不可信数据可能导致任意代码执行;推荐在纯Python、跨语言需求低且数据源可信的场景中使用,否则应选用JSON等更安全的替代方案。

python怎么序列化一个对象(pickle)_pickle模块对象序列化与反序列化

Python的

pickle
模块提供了一种将Python对象序列化(即转换为字节流)和反序列化(即从字节流恢复为Python对象)的机制。这在需要持久化对象、在不同进程间传递对象或通过网络传输对象时非常有用。简单来说,它能把你的Python数据结构“冻结”成一串字节,然后随时“解冻”回来。

解决方案

使用

pickle
模块进行对象的序列化与反序列化,主要涉及
dump/load
dumps/loads
两对函数。

当你需要将一个Python对象保存到文件(或任何文件状对象)时,可以使用

pickle.dump()
。它接收两个参数:要序列化的对象和文件对象。

import pickle

data = {
    'name': '张三',
    'age': 30,
    'city': '北京',
    'scores': [95, 88, 92]
}

# 序列化到文件
try:
    with open('my_data.pkl', 'wb') as f: # 注意这里是'wb',写入二进制模式
        pickle.dump(data, f)
    print("数据已成功序列化并保存到 my_data.pkl")
except Exception as e:
    print(f"序列化失败: {e}")

# 从文件反序列化
try:
    with open('my_data.pkl', 'rb') as f: # 注意这里是'rb',读取二进制模式
        loaded_data = pickle.load(f)
    print("数据已成功从 my_data.pkl 反序列化:")
    print(loaded_data)
except FileNotFoundError:
    print("文件 my_data.pkl 不存在。")
except Exception as e:
    print(f"反序列化失败: {e}")

如果你的需求是把对象序列化成一个字节字符串,而不是直接写入文件,那么

pickle.dumps()
就派上用场了。它只接收一个参数:要序列化的对象,然后返回一个字节串。对应的反序列化函数是
pickle.loads()
,它接收一个字节串并返回原始的Python对象。

立即学习Python免费学习笔记(深入)”;

import pickle

class MyObject:
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return f"MyObject(value={self.value})"

obj = MyObject(123)
another_data = {'id': 1, 'object': obj}

# 序列化为字节串
pickled_bytes = pickle.dumps(another_data)
print(f"序列化后的字节串: {pickled_bytes}")

# 从字节串反序列化
unpickled_data = pickle.loads(pickled_bytes)
print(f"反序列化后的数据: {unpickled_data}")
print(f"反序列化后的对象类型: {type(unpickled_data['object'])}")
print(f"反序列化后的对象值: {unpickled_data['object'].value}")

pickle
模块的安全性如何?使用时需要注意哪些风险?

谈到

pickle
,安全性是一个绕不开的话题,而且通常是排在首位的注意事项。我的个人经验是,如果你不了解其潜在风险,最好不要在处理不可信数据时使用它。
pickle
模块在设计上,并没有考虑对抗恶意构造的数据。这意味着,如果你反序列化一个由攻击者精心构造的字节流,它可能会在你的系统上执行任意代码。这可不是开玩笑的,它能直接导致严重的安全漏洞。

为什么会这样呢?因为

pickle
在反序列化时,实际上会执行一些操作来重建Python对象,包括调用类的方法、构造函数等。如果这些操作被恶意利用,就能触发代码执行。举个例子,一个攻击者可以构造一个字节流,使得在反序列化时,它会导入一个系统模块,然后调用一个危险的函数,比如删除文件或者执行shell命令。

所以,我的建议是:永远不要反序列化来自不可信源的

pickle
数据。如果你确实需要处理外部数据,但又无法保证其来源的绝对安全,那么
pickle
就不是你的首选。在这种情况下,更安全的替代方案是使用JSON、YAML或Protocol Buffers等跨语言的序列化格式。这些格式通常只允许表示基本数据类型(字符串、数字、列表、字典等),不会涉及代码执行,因此安全性更高。当然,它们也有各自的限制,比如不能直接序列化复杂的Python对象,需要手动进行转换。但为了安全,这点额外的开发工作是值得的。

如何序列化自定义类或复杂对象?
pickle
在处理这些情况时有什么限制?

pickle
模块在处理自定义类和复杂对象方面,确实展现了其强大之处。它通常能够“开箱即用”地序列化大多数Python对象,包括自定义类的实例。这得益于
pickle
能够保存对象的类信息以及其状态(实例属性)。当反序列化时,
pickle
会找到对应的类定义,然后根据保存的状态重新创建对象。

然而,这并不是没有限制的。最常见的一个限制是,在反序列化时,自定义类的定义必须在当前环境中可用。也就是说,如果你序列化了一个

MyClass
的实例,那么在进行反序列化的程序中,
MyClass
的定义(所在的模块和代码)必须能够被Python找到。如果找不到,就会抛出
AttributeError
ModuleNotFoundError
。这对于在同一应用的不同部分或同一台机器上的不同进程间传递对象通常不是问题,但如果跨版本、跨环境,或者类定义发生了变化,就可能遇到麻烦。

另外,有些Python对象是无法被

pickle
序列化的。这包括:

Joker AIx
Joker AIx

一站式AI创意生产平台,覆盖图像、视频、音频、文案全品类创作

下载
  • 文件句柄、网络连接、数据库连接:这些是与操作系统资源绑定的对象,无法直接序列化其状态。
  • 匿名函数(lambda)和嵌套函数
    pickle
    通常无法可靠地序列化这些。
  • 线程锁、信号量等同步原语:这些也与运行时状态紧密相关。
  • 一些特殊的内置类型或C扩展对象:它们可能没有实现
    pickle
    协议。

对于这些无法直接序列化的对象,或者当你需要对序列化过程进行更精细的控制时,

pickle
提供了一些“魔术方法”:
__getstate__
__setstate__

  • __getstate__(self)
    :这个方法应该返回一个代表对象状态的对象,这个对象是可序列化的。
    pickle
    会序列化这个返回值而不是对象的
    __dict__
  • __setstate__(self, state)
    :这个方法在反序列化时被调用,接收
    __getstate__
    返回的状态对象,然后用它来恢复对象的状态。

通过这两个方法,你可以自定义哪些数据需要被序列化,以及如何重建对象。例如,你可以选择不序列化一个文件句柄,而只保存其路径,然后在

__setstate__
中重新打开文件。

import pickle

class MyResource:
    def __init__(self, filename):
        self.filename = filename
        self.file_handle = open(filename, 'w') # 模拟一个不可序列化的资源
        self.file_handle.write("Initial content\n")

    def __getstate__(self):
        # 返回一个可序列化的状态,这里只保存文件名
        state = {'filename': self.filename}
        return state

    def __setstate__(self, state):
        # 从状态中恢复对象,重新打开文件
        self.filename = state['filename']
        self.file_handle = open(self.filename, 'a') # 以追加模式重新打开
        print(f"资源 {self.filename} 已重新打开。")

    def write_data(self, data):
        self.file_handle.write(data + '\n')

    def close(self):
        self.file_handle.close()
        print(f"资源 {self.filename} 已关闭。")

# 创建并序列化对象
resource_obj = MyResource('temp_log.txt')
resource_obj.write_data("First line.")
resource_obj.close() # 序列化前关闭文件,避免问题

pickled_resource = pickle.dumps(resource_obj)

# 反序列化对象
unpickled_resource = pickle.loads(pickled_resource)
unpickled_resource.write_data("Second line after unpickling.")
unpickled_resource.close()

# 清理
import os
os.remove('temp_log.txt')

这个例子展示了如何通过

__getstate__
__setstate__
来处理一个包含文件句柄这种不可序列化资源的自定义类。

pickle
与其他序列化方法(如JSON、msgpack)有何不同?何时选择
pickle

pickle
、JSON和msgpack都是常见的序列化工具,但它们各有侧重,适用于不同的场景。理解它们之间的差异,能帮助我们做出更明智的选择。

pickle

  • Python特有:它是Python语言专用的序列化格式,这意味着序列化后的数据只能被Python程序反序列化。
  • 二进制格式:序列化结果是二进制字节流,通常比文本格式更紧凑。
  • 功能强大:能够序列化几乎所有Python对象,包括自定义类实例、函数、甚至模块(尽管这通常不推荐,且有安全风险)。它能保留Python对象的完整结构和类型信息。
  • 安全性低:如前所述,不应反序列化不可信数据。

JSON (JavaScript Object Notation):

  • 跨语言:JSON是一种语言无关的文本格式,被几乎所有主流编程语言支持。
  • 文本格式:人类可读,易于调试。
  • 数据类型有限:主要支持基本数据类型:字符串、数字、布尔值、列表、字典、null。无法直接表示Python的元组、集合、日期时间对象或自定义类实例。需要手动进行转换。
  • 安全性高:由于只处理数据,不涉及代码执行,因此相对安全。

msgpack:

  • 跨语言:与JSON类似,msgpack也是一种跨语言的二进制序列化格式。
  • 二进制格式:比JSON更紧凑,解析速度通常更快。
  • 数据类型比JSON略多:支持JSON的基本类型,并能更高效地处理二进制数据。
  • 安全性高:同样不涉及代码执行,安全性良好。

何时选择

pickle

我的经验是,

pickle
的最佳使用场景是在受信任的环境中,进行Python程序内部或Python程序之间的对象持久化和通信。具体来说:

  1. 进程间通信 (IPC):当你在同一个系统上运行多个Python进程,并且需要高效地传递复杂的Python对象时,
    pickle
    是一个很好的选择。例如,使用
    multiprocessing
    模块时,它在幕后就使用了
    pickle
  2. 对象持久化:将Python对象保存到磁盘,以便稍后由同一个Python程序(或兼容版本的Python程序)加载和恢复。这对于缓存计算结果、保存程序状态等非常有用。
  3. 需要保留Python对象完整性:如果你的对象包含复杂的结构,比如自定义类的实例、函数引用、集合、元组等,并且你希望在反序列化后完全恢复这些对象的原始类型和结构,那么
    pickle
    是首选,因为它能做到这一点而无需额外的类型映射或转换。
  4. 性能要求较高,且数据源可信:在Python内部,
    pickle
    通常比JSON等文本格式有更好的序列化和反序列化性能,因为它不需要进行文本解析和数据类型转换。

总结一下,如果你的应用场景是纯Python环境,且数据来源绝对可信,同时你需要处理复杂且多样化的Python对象,那么

pickle
无疑是最方便和强大的选择。但一旦涉及跨语言、不确定数据来源或对数据格式有严格要求(如Web API),那么JSON或msgpack会是更稳妥、更通用的方案。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

457

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

547

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

335

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

82

2025.09.10

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

338

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

225

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

138

2026.02.12

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号