pickle 是 Python 标准库中的一个模块,用于对象的序列化(serialization)和反序列化(deserialization)。
序列化是将对象转换为字节流的过程,而反序列化则是从字节流恢复对象的过程。
通过 pickle 模块,可以将 Python 对象保存到文件中,或者通过网络传输,以及存储在数据库中。
主要功能
序列化(dump):将 Python 对象转换为字节流并保存到文件或其它存储介质中。
反序列化(load):从字节流中读取并重建原始的 Python 对象。
常用函数
pickle.dump(obj, file, protocol=None):将对象 obj 序列化并写入到文件 file 中。file 需要是以二进制模式打开的文件对象,例如 open('file.pkl', 'wb')。protocol 是序列化协议的版本,可以选择不同的协议以优化性能或兼容性。
pickle.load(file):从以二进制模式打开的文件 file 中读取并反序列化对象。例如 open('file.pkl', 'rb')。
pickle.dumps(obj):将对象 obj 序列化为字节对象(bytes),而不是写入文件。
pickle.loads(bytes_object):从字节对象(bytes)中反序列化并重建对象。
示例
序列化与反序列化到文件:
import pickle
# 假设有一个要保存的 Python 对象
data = {"name": "张三", "age": 30, "city": "上海"}
# 将对象保存到文件
with open("data.pkl", "wb") as file:
pickle.dump(data, file)
# 从文件中读取对象
with open("data.pkl", "rb") as file:
loaded_data = pickle.load(file)
print(loaded_data) # 输出: {'name': '张三', 'age': 30, 'city': '上海'}
序列化与反序列化到字节对象:
import pickle
# 假设有一个要保存的 Python 对象
data = ["苹果", "香蕉", "梨"]
# 将对象序列化为字节对象
serialized_data = pickle.dumps(data)
# 从字节对象中反序列化
deserialized_data = pickle.loads(serialized_data)
print(deserialized_data) # 输出: ['苹果', '香蕉', '梨']
将文件夹序列化到字节对象以及反操作:
import os
import pickle
# 序列化文件夹到文件
def serialize_files_in_directory_with_paths(directory, output_file):
serialized_data = []
for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
try:
with open(file_path, 'rb') as f:
file_content = f.read()
serialized_content = pickle.dumps((file_path, file_content))
serialized_data.append(serialized_content)
except Exception as e:
print(f"无法序列化文件 {file_path}: {e}")
with open(output_file, 'wb') as f:
for data in serialized_data:
f.write(data)
# 反序列化文件到文件夹
def deserialize_files_from_file_with_paths(byte_stream_file, output_directory):
if not os.path.exists(output_directory):
os.makedirs(output_directory)
with open(byte_stream_file, 'rb') as f:
serialized_data = f.read()
offset = 0
while offset < len(serialized_data):
try:
file_path, file_content = pickle.loads(serialized_data[offset:])
offset += len(pickle.dumps((file_path, file_content)))
file_dir = os.path.dirname(file_path)
if not os.path.exists(file_dir):
os.makedirs(file_dir)
with open(file_path, 'wb') as output_file:
output_file.write(file_content)
except Exception as e:
print(f"无法反序列化字节流: {e}")
break
# 序列化使用示例
directory_path = 'D:\\需要序列化的目录\\需要序列化的目录多层结构' # 需要序列化的目录,比如位于D:\
output_file_path = 'path/to/output/file.pkl'
serialize_files_in_directory_with_paths(directory_path, output_file_path)
# 反序列化使用示例
byte_stream_file_path = 'file.pkl'
output_directory_path = 'D:\\' # 反序列化后的文件保存的目录,必须是D:\的根目录,否则会反序列化失败
deserialize_files_from_file_with_paths(byte_stream_file_path, output_directory_path)
注意事项
安全性:由于 pickle 可以执行反序列化过程中的任意代码,因此从不可信来源加载 pickle 数据可能会带来安全风险。攻击者可以通过恶意构造的 pickle 数据执行任意代码。因此,除非数据来源可信,否则不要轻易使用 pickle.load 或 pickle.loads。
版本兼容性:不同版本的 Python 可能对 pickle 的协议有不同的支持。高版本的 Python 通常支持低版本的协议,但反之不一定成立。因此,在跨 Python 版本使用 pickle 数据时,需要注意协议的兼容性。
不可移植性:pickle 数据是特定于 Python 的,因此不能在非 Python 环境中直接使用。如果需要跨语言的序列化方式,可以考虑使用 JSON、XML 或 MessagePack 等。
性能:在某些情况下,pickle 的性能可能不是最佳选择,尤其是对于非常大的对象。可以考虑使用其他序列化库,如 json(适用于简单数据结构)或 msgpack(更高效的二进制格式)。
常见用途
持久化存储:将 Python 对象保存到磁盘,以便稍后继续使用。
缓存:将计算结果缓存到文件中,避免重复计算。
数据传输:在 Python 程序之间或通过网络传输对象。一个典型应用是CIFAR10数据集,CIFAR10数据集的训练集有50000个图像文件,如果在操作系统中使用直接读写的方式移动这50000个文件,就意味着要执行50000次文件的读和写,效率很低。下图就是一次复制粘贴实测:
虽然所有文件只有大约120M大小,用了12分钟才完成。
使用上面的代码将所有文件转换成一个字节流文件:
得到的字节流文件:
对这个120M的单个文件的读写瞬间就可以完成。
标签:模块,Python,data,file,path,序列化,pickle From: https://blog.csdn.net/xulibo5828/article/details/143230208