Python3 Pickle 模塊基本用法詳解
在 Python 中,pickle模塊是實現(xiàn)對象序列化與反序列化的核心工具,它能將 Python 對象(如列表、字典、類實例等)轉(zhuǎn)換為字節(jié)流以便存儲或傳輸,也能將字節(jié)流恢復(fù)為原始對象。本文將系統(tǒng)講解pickle模塊的工作原理、基本用法、高級特性及注意事項,幫助你在實際開發(fā)中靈活運(yùn)用對象持久化技術(shù)。
一、核心概念:序列化與反序列化
- 序列化(pickling):將 Python 對象轉(zhuǎn)換為字節(jié)流(二進(jìn)制數(shù)據(jù))的過程,便于存儲到文件或通過網(wǎng)絡(luò)傳輸。
- 反序列化(unpickling):將字節(jié)流恢復(fù)為 Python 對象的過程,從文件或網(wǎng)絡(luò)數(shù)據(jù)中重建原始對象。
pickle模塊支持幾乎所有 Python 內(nèi)置對象的序列化,包括:
- 基本數(shù)據(jù)類型(int、float、str、bool、None);
- 容器類型(list、tuple、dict、set);
- 自定義類實例、函數(shù)、類(需注意特殊處理)。
二、基本用法:pickle 的核心函數(shù)
pickle模塊的核心功能通過四個函數(shù)實現(xiàn):dump()、dumps()、load()、loads(),區(qū)分在于是否直接操作文件對象。
1. 序列化:dump()與dumps()
pickle.dump(obj, file, protocol=None):將對象obj序列化后寫入文件對象file(需以二進(jìn)制模式打開)。pickle.dumps(obj, protocol=None):將對象obj序列化為字節(jié)流(bytes類型),返回該字節(jié)流。
示例:序列化基本對象
import pickle
# 定義一個復(fù)雜對象(包含多種類型)
data = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "hiking"],
"is_student": False,
"scores": (90.5, 85.0)
}
# 方法1:用dumps()序列化為字節(jié)流
data_bytes = pickle.dumps(data)
print("序列化結(jié)果(字節(jié)流):", data_bytes) # 輸出b'\x80\x04...'(二進(jìn)制數(shù)據(jù))
# 方法2:用dump()序列化到文件
with open("data.pkl", "wb") as f: # 必須用二進(jìn)制模式"wb"
pickle.dump(data, f)2. 反序列化:load()與loads()
pickle.load(file):從文件對象file(二進(jìn)制模式打開)中讀取字節(jié)流,反序列化為 Python 對象并返回。pickle.loads(bytes_obj):將字節(jié)流bytes_obj反序列化為 Python 對象并返回。
示例:反序列化恢復(fù)對象
import pickle
# 方法1:用loads()從字節(jié)流反序列化
data_bytes = pickle.dumps({"name": "Alice"})
restored_data = pickle.loads(data_bytes)
print("從字節(jié)流恢復(fù):", restored_data) # 輸出 {'name': 'Alice'}
# 方法2:用load()從文件反序列化
with open("data.pkl", "rb") as f: # 必須用二進(jìn)制模式"rb"
restored_from_file = pickle.load(f)
print("從文件恢復(fù):", restored_from_file) # 輸出原始data字典三、高級特性:自定義類的序列化
pickle不僅支持內(nèi)置對象,還能序列化自定義類的實例,但需要注意類定義的可訪問性(反序列化時需能導(dǎo)入原類)。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}!"
# 創(chuàng)建實例
person = Person("Bob", 25)
# 序列化
person_bytes = pickle.dumps(person)
# 反序列化(需確保Person類在當(dāng)前作用域中)
restored_person = pickle.loads(person_bytes)
print(restored_person.greet()) # 輸出 "Hello, I'm Bob!"
print(restored_person.age) # 輸出 252. 自定義序列化邏輯(__getstate__與__setstate__)
默認(rèn)情況下,pickle會序列化對象的__dict__(實例屬性字典),但你可以通過以下方法自定義序列化內(nèi)容:
__getstate__():返回需要序列化的數(shù)據(jù)(如字典),替代默認(rèn)的__dict__;__setstate__(state):接收反序列化后的數(shù)據(jù)state,用于恢復(fù)對象狀態(tài)。
示例:過濾敏感信息
import pickle
class User:
def __init__(self, username, password):
self.username = username
self.password = password # 敏感信息,不希望被序列化
# 自定義序列化內(nèi)容:只保留username
def __getstate__(self):
return {"username": self.username}
# 自定義反序列化邏輯:恢復(fù)狀態(tài)
def __setstate__(self, state):
self.username = state["username"]
self.password = "default" # 反序列化時密碼設(shè)為默認(rèn)值
# 創(chuàng)建實例
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"(敏感信息未被序列化)四、協(xié)議版本:影響序列化效率與兼容性
pickle支持多種序列化協(xié)議(版本),不同版本在效率、兼容性上有差異:
- 協(xié)議 0:文本格式,兼容舊版本 Python(默認(rèn)在 Python 2 中),效率低;
- 協(xié)議 1:二進(jìn)制格式,兼容 Python 2 和 3;
- 協(xié)議 2:Python 2.3 + 引入,支持新特性(如新式類);
- 協(xié)議 3:Python 3.0 + 引入,不兼容 Python 2;
- 協(xié)議 4:Python 3.4 + 引入,支持更大對象、更多類型(如
bytes、set等),是 Python 3.8 + 的默認(rèn)協(xié)議。
指定協(xié)議版本:通過protocol參數(shù)設(shè)置(如protocol=4),值越高通常效率越好(但兼容性可能降低)。
import pickle data = [i for i in range(1000)] # 使用協(xié)議4序列化(效率更高) data_bytes = pickle.dumps(data, protocol=4)
五、注意事項:安全與兼容性問題
1. 安全性風(fēng)險:反序列化不可信數(shù)據(jù)
pickle反序列化時會執(zhí)行字節(jié)流中包含的代碼,若從不可信來源(如網(wǎng)絡(luò)、未知文件)加載數(shù)據(jù),可能導(dǎo)致惡意代碼執(zhí)行(如刪除文件、竊取信息)。
禁止反序列化未知來源的數(shù)據(jù),若需網(wǎng)絡(luò)傳輸,建議使用更安全的格式(如 JSON,僅支持基礎(chǔ)類型)。
2. 兼容性問題
- 類定義變化:若反序列化時的類定義與序列化時不同(如新增 / 刪除屬性、修改類名),可能導(dǎo)致反序列化失??;
- 跨版本兼容性:高版本協(xié)議(如 4)序列化的數(shù)據(jù)無法在低版本 Python(如 3.3 以下)中反序列化;
- 模塊路徑變化:若類所在的模塊路徑改變(如從
moduleA移到moduleB),反序列化時需確保能正確導(dǎo)入類。
3. 不支持的類型
部分 Python 對象無法被序列化,例如:
- 生成器、lambda 函數(shù)(匿名函數(shù));
- 線程、進(jìn)程、文件對象等與系統(tǒng)資源相關(guān)的對象;
- 某些內(nèi)置模塊的對象(如
sys.stdin)。
序列化這些對象會拋出PickleError。
六、實戰(zhàn)場景:對象持久化與數(shù)據(jù)緩存
1. 保存程序狀態(tài)(持久化)
將程序運(yùn)行中的關(guān)鍵對象(如配置、中間結(jié)果)保存到文件,下次運(yùn)行時直接恢復(fù),避免重復(fù)計算。
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("從緩存加載結(jié)果")
except FileNotFoundError:
# 無緩存則計算并保存
result = expensive_computation()
with open("result_cache.pkl", "wb") as f:
pickle.dump(result, f)
print("計算完成并緩存")2. 跨進(jìn)程數(shù)據(jù)傳遞
在多進(jìn)程編程中,pickle是進(jìn)程間傳遞復(fù)雜對象的默認(rèn)方式(如multiprocessing模塊依賴pickle序列化數(shù)據(jù))。
from multiprocessing import Process
import pickle
def process_data(data):
print("子進(jìn)程接收數(shù)據(jù):", data)
if __name__ == "__main__":
# 定義復(fù)雜對象
data = {"task": "process", "params": [1, 2, 3]}
# 多進(jìn)程會自動序列化data并傳遞給子進(jìn)程
p = Process(target=process_data, args=(data,))
p.start()
p.join()七、與 JSON 的對比:何時用 pickle?
| 特性 | pickle | JSON |
|---|---|---|
| 支持類型 | 幾乎所有 Python 對象(類實例、函數(shù)等) | 僅基礎(chǔ)類型(str、int、list、dict 等) |
| 數(shù)據(jù)格式 | 二進(jìn)制(不可讀) | 文本(人類可讀) |
| 安全性 | 不安全(可能執(zhí)行惡意代碼) | 安全(純數(shù)據(jù)解析) |
| 跨語言支持 | 僅 Python | 所有主流語言支持 |
| 用途 | Python 內(nèi)部對象持久化、進(jìn)程間通信 | 跨語言數(shù)據(jù)交換、配置文件 |
選擇建議:
- 僅在 Python 生態(tài)內(nèi)使用,且需要序列化復(fù)雜對象(如類實例)→ 用
pickle; - 需跨語言交互,或數(shù)據(jù)需人類可讀、可編輯 → 用 JSON。
總結(jié)
pickle模塊是 Python 對象序列化的核心工具,通過dump()/dumps()和load()/loads()實現(xiàn)對象與字節(jié)流的轉(zhuǎn)換,支持自定義類實例及復(fù)雜數(shù)據(jù)結(jié)構(gòu)。但需注意其安全性風(fēng)險(禁止處理不可信數(shù)據(jù))和兼容性限制。
在實際開發(fā)中,pickle適用于 Python 內(nèi)部的對象持久化、進(jìn)程間通信等場景,是提升程序效率和靈活性的重要手段。合理使用pickle,可簡化復(fù)雜數(shù)據(jù)的存儲與傳輸邏輯。
到此這篇關(guān)于Python3 Pickle 模塊詳解的文章就介紹到這了,更多相關(guān)python pickle 模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
OpenCV連通域數(shù)量統(tǒng)計學(xué)習(xí)示例
這篇文章主要為大家介紹了OpenCV連通域數(shù)量統(tǒng)計示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
對python數(shù)據(jù)清洗容易遇到的函數(shù)-re.sub bytes string詳解
今天小編就為大家分享一篇對python數(shù)據(jù)清洗容易遇到的函數(shù)-re.sub bytes string詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-07-07
Python配置文件解析模塊ConfigParser使用實例
這篇文章主要介紹了Python配置文件解析模塊ConfigParser使用實例,本文講解了figParser簡介、ConfigParser 初始工作、ConfigParser 常用方法、ConfigParser使用實例等內(nèi)容,需要的朋友可以參考下2015-04-04
Win10?Anaconda?新建環(huán)境安裝python-pcl的步驟
這篇文章主要介紹了Win10?Anaconda?新建環(huán)境安裝python-pcl的方法,至于VS環(huán)境下安裝C++?版本的pcl也可以按照此文提供的步驟安裝實現(xiàn),需要的朋友可以參考下2022-04-04

