python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > python pickle 模块

Python3 Pickle 模块基本用法详解

作者:小陶coding

本文将系统讲解pickle模块的工作原理、基本用法、高级特性及注意事项,帮助你在实际开发中灵活运用对象持久化技术,感兴趣的朋友跟随小编一起看看吧

在 Python 中,pickle模块是实现对象序列化与反序列化的核心工具,它能将 Python 对象(如列表、字典、类实例等)转换为字节流以便存储或传输,也能将字节流恢复为原始对象。本文将系统讲解pickle模块的工作原理、基本用法、高级特性及注意事项,帮助你在实际开发中灵活运用对象持久化技术。

一、核心概念:序列化与反序列化

pickle模块支持几乎所有 Python 内置对象的序列化,包括:

二、基本用法:pickle 的核心函数

pickle模块的核心功能通过四个函数实现:dump()dumps()load()loads(),区分在于是否直接操作文件对象。

1. 序列化:dump()与dumps()

示例:序列化基本对象

import pickle
# 定义一个复杂对象(包含多种类型)
data = {
    "name": "Alice",
    "age": 30,
    "hobbies": ["reading", "hiking"],
    "is_student": False,
    "scores": (90.5, 85.0)
}
# 方法1:用dumps()序列化为字节流
data_bytes = pickle.dumps(data)
print("序列化结果(字节流):", data_bytes)  # 输出b'\x80\x04...'(二进制数据)
# 方法2:用dump()序列化到文件
with open("data.pkl", "wb") as f:  # 必须用二进制模式"wb"
    pickle.dump(data, f)

2. 反序列化:load()与loads()

示例:反序列化恢复对象

import pickle
# 方法1:用loads()从字节流反序列化
data_bytes = pickle.dumps({"name": "Alice"})
restored_data = pickle.loads(data_bytes)
print("从字节流恢复:", restored_data)  # 输出 {'name': 'Alice'}
# 方法2:用load()从文件反序列化
with open("data.pkl", "rb") as f:  # 必须用二进制模式"rb"
    restored_from_file = pickle.load(f)
print("从文件恢复:", restored_from_file)  # 输出原始data字典

三、高级特性:自定义类的序列化

pickle不仅支持内置对象,还能序列化自定义类的实例,但需要注意类定义的可访问性(反序列化时需能导入原类)。

1. 基本自定义类序列化

import pickle
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def greet(self):
        return f"Hello, I'm {self.name}!"
# 创建实例
person = Person("Bob", 25)
# 序列化
person_bytes = pickle.dumps(person)
# 反序列化(需确保Person类在当前作用域中)
restored_person = pickle.loads(person_bytes)
print(restored_person.greet())  # 输出 "Hello, I'm Bob!"
print(restored_person.age)      # 输出 25

2. 自定义序列化逻辑(__getstate__与__setstate__)

默认情况下,pickle会序列化对象的__dict__(实例属性字典),但你可以通过以下方法自定义序列化内容:

示例:过滤敏感信息

import pickle
class User:
    def __init__(self, username, password):
        self.username = username
        self.password = password  # 敏感信息,不希望被序列化
    # 自定义序列化内容:只保留username
    def __getstate__(self):
        return {"username": self.username}
    # 自定义反序列化逻辑:恢复状态
    def __setstate__(self, state):
        self.username = state["username"]
        self.password = "default"  # 反序列化时密码设为默认值
# 创建实例
user = User("alice123", "secret123")
# 序列化
user_bytes = pickle.dumps(user)
# 反序列化
restored_user = pickle.loads(user_bytes)
print(restored_user.username)  # 输出 "alice123"
print(restored_user.password)  # 输出 "default"(敏感信息未被序列化)

四、协议版本:影响序列化效率与兼容性

pickle支持多种序列化协议(版本),不同版本在效率、兼容性上有差异:

指定协议版本:通过protocol参数设置(如protocol=4),值越高通常效率越好(但兼容性可能降低)。

import pickle
data = [i for i in range(1000)]
# 使用协议4序列化(效率更高)
data_bytes = pickle.dumps(data, protocol=4)

五、注意事项:安全与兼容性问题

1. 安全性风险:反序列化不可信数据

pickle反序列化时会执行字节流中包含的代码,若从不可信来源(如网络、未知文件)加载数据,可能导致恶意代码执行(如删除文件、窃取信息)。

禁止反序列化未知来源的数据,若需网络传输,建议使用更安全的格式(如 JSON,仅支持基础类型)。

2. 兼容性问题

3. 不支持的类型

部分 Python 对象无法被序列化,例如:

序列化这些对象会抛出PickleError

六、实战场景:对象持久化与数据缓存

1. 保存程序状态(持久化)

将程序运行中的关键对象(如配置、中间结果)保存到文件,下次运行时直接恢复,避免重复计算。

import pickle
import time
def expensive_computation():
    # 模拟耗时计算
    time.sleep(3)
    return [i**2 for i in range(1000)]
# 检查是否有缓存
try:
    with open("result_cache.pkl", "rb") as f:
        result = pickle.load(f)
        print("从缓存加载结果")
except FileNotFoundError:
    # 无缓存则计算并保存
    result = expensive_computation()
    with open("result_cache.pkl", "wb") as f:
        pickle.dump(result, f)
    print("计算完成并缓存")

2. 跨进程数据传递

在多进程编程中,pickle是进程间传递复杂对象的默认方式(如multiprocessing模块依赖pickle序列化数据)。

from multiprocessing import Process
import pickle
def process_data(data):
    print("子进程接收数据:", data)
if __name__ == "__main__":
    # 定义复杂对象
    data = {"task": "process", "params": [1, 2, 3]}
    # 多进程会自动序列化data并传递给子进程
    p = Process(target=process_data, args=(data,))
    p.start()
    p.join()

七、与 JSON 的对比:何时用 pickle?

特性pickleJSON
支持类型几乎所有 Python 对象(类实例、函数等)仅基础类型(str、int、list、dict 等)
数据格式二进制(不可读)文本(人类可读)
安全性不安全(可能执行恶意代码)安全(纯数据解析)
跨语言支持仅 Python所有主流语言支持
用途Python 内部对象持久化、进程间通信跨语言数据交换、配置文件

选择建议

总结

pickle模块是 Python 对象序列化的核心工具,通过dump()/dumps()load()/loads()实现对象与字节流的转换,支持自定义类实例及复杂数据结构。但需注意其安全性风险(禁止处理不可信数据)和兼容性限制。

在实际开发中,pickle适用于 Python 内部的对象持久化、进程间通信等场景,是提升程序效率和灵活性的重要手段。合理使用pickle,可简化复杂数据的存储与传输逻辑。

到此这篇关于Python3 Pickle 模块详解的文章就介绍到这了,更多相关python pickle 模块内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文