Python Cookbook-7.2 使用 pickle 和 cPickle 模块序列化数据

任务

你想以某种可以接受的速度序列化和重建Python 数据结构,这些数据既包括基本Python 对象也包括类和实例。

解决方案

如果你不想假设你的数据完全由基本 Python 对象组成,或者需要在不同的 Python 版本之间移植,再或者需要将序列化后的形态作为文本传递,那么最好的序列化数据的方法是 cPickle 模块(pickle 模块是完全用 Python 实现的,而且完全可以替代 cPickle,但问题是它比较慢,除非你没有cPickle用,不然它并不是最好的选择)。举个例子假设你有:

data = {12:'twelve', 'feep':list('ciao'), 1.23:4+5j, (1,2,3):u'wer'}

可以将 data 序列化为文本字符串:

import cPickle
text = cPickle.dumps(data)

或者转化为二进制串,这种选择通常更快而且更节省空间:

bytes = cPickle.dumps(data,2)

现在,可以将text和 bytes按照意愿进行各种处理(比如,通过网络传递,作为BLOB放入数据库中,见 7.10节、7.11节和 7.12节),只要你不修改 text和 bytes 本身。对于bytes 而言,那意味着应该保证其二进制字节序不被改变,对于text 而言,应该保证它的文本结构不被改变,包括换行符。之后,无论在什么计算机体系结构之下,无论用什么版本的 Python,你都可以重新构建出那些数据:

redata1 = cPickle.loads(text)
redata2 = cPickle.loads(bytes)

每个调用创建出来的数据结构都等于原数据。比较特别的是,字典的键在原数据和新建数据中的顺序都是任意的,但这个顺序本身是有意义的,因此也会被保存。无须告诉 cPickle.loads 原先的 dumps 是否使用了文本模式(这是默认的模式,可以由一些很老的 Python 版本读取)或二进制模式(快速目紧凑),loads 可以通过检查参数的内容自行判断。

当你希望将数据写入文件时,可以直接使用cPickle的dump函数,它允许你将多个数据结构一个接一个地写入到同一个文件:

ouf = open('datafile.txt','w')
cPickle.dump(data,ouf)
cPickle.dump('some string',ouf)
cPickle.dump(range(19),ouf)
ouf.close()

一旦你做完这些事,就可以从 datafle.txt 中以相同的顺序一个接一个地恢复原来的数据结构:

inf = open('datafile.txt')
a = cPickle.load(inf)
b = cPickle.load(inf)
c = cPickle.load(inf)
inf.close()

还可以给 cPickle.dump 传递值为2的第三个参数,这相当于告诉 cPickle.dump 以二进制的形式(快速且紧凑)序列化数据,但同时数据文件也必须以二进制模式打开,而不能是默认的文本模式,无论你是想写入或是取出数据。

讨论

Python 提供了几种方法来序列化数据(比如,将数据转化为字节串,存入磁盘或数据库,或者通过网络传递)以及从序列化形式重新构建数据。最好的方式是使用cPickle模块。它有一个纯 Python 的对应物,叫做 pickle(cPickle 模块是用C编写的 Python 扩展),但速度就慢得多了,只有在没有cPickle 的情况下才应该考虑使用它(比如,将Python 移植到容量很小的手机中,必须节省每一个字节,所以只能安装那些完全不可或缺的 Python 标准库的子集)。然而,在任何能够使用 pickle 的地方,都可以将其替换为 cPickle:可以用其中的一个将数据序列化,用另一个恢复并重新构建数据,而不会有任何问题。

cPickle 支持绝大多数的基本数据类型(如字典、列表、元组、数字、字符串)以及它们的各种组合形式,同时也支持类和实例。而对类和实例所做的处理仅仅涉及到数据与代码无关(cPikle 对象并不知道怎样序列化代码对象,这可能是因为在不同的 Python发行版之间的可移植性完全无法保证,因此序列化代码对象意义不大。如果你不需要考虑跨版本问题的话,可参看7.6节介绍的对代码对象的序列化方法)。7.4节还有更多的用 cPickle 处理类和实例的细节。

cPickle 保证了在不同 Python 发行版之间的兼容性,也保证了对于特定计算机体系结构的独立性。即使你升级了你的Python 发行版,通过cPickle处理的序列化数据仍然可以被读取,而且即使在不同的计算机上,这种序列化和反序列化操作也是保证可用的。

cPickle 的 dumps 函数接受任何 Python 数据结构作为参数,并返回一个字符串。如果用2 作为 dumps 的第二个参数,dumps 将返回一个字节串:操作速度会更快,而且产生的串长度会更短。可以给 loads函数传递字符串或者字节串,它都将返回一个Python 数据结构,此数据等同于(=)原来的数据。在 dumps 和 loads 调用之间,可以以任意方式处置那个字符串或字节串,比如通过网络传输,存入数据库并读取,或者加密之后再解密。只要这个串本身的结构没有被改变,loads都能够正确地读取(即使是在不同的平台上,或者用更新的发行的版本)。如果需要用老版本(早于2.3)的Python 处理数据,可考虑用1作为第二个参数:其操作速度会比较慢,产生的结果串也不如用2作参数产生的串紧凑短小,但这个串可以被老版本和最新的 Python,甚至以后的Python版本读取。

当需要将数据存入文件时,可以使用cPickle的dump函数,它接受两个参数:需要处理的数据结构和一个打开的文件对象,或者一个类文件对象。如果文件是以二进制输入输出方式打开的,而不是默认方式(文本模式),可以把2作为它的第三个参数,明确要求使用二进制格式,这样速度更快也更紧凑(或用1作为第三个参数来产生结果串,这样速度不快,要求的空间也更多,但是它能够被很老的,甚至早于 2.3的 Python版本读取)。dump 优于 dumps 的地方在于,通过 dump,可以进行几个调用,一个接一个地将不同的数据结构存入到同一个打开的文件。每个数据结构在存入时还会带有附加的信息,如这个串的长度。因此,当你以后打开此文件读取数据(二进制读取,如果你当初要求以二进制格式存入的话)并反复调用cPickle.load 时,可将文件作为其参数,根据顺序一个接一个地构建出原来的数据结构。而load 的返回值,就像 loads 的返回值一样,是一个完全等同于原数据的新的数据结构。

那些习惯于其他语言和库提供的“序列化”工具的用户可能会问,对于想要序列化和反序列化的对象的大小,pickle会不会有什么限制。答案是:没有。你的计算机的内存可能是唯一的限制,如果你的计算机的内存非常大,pickle 在实践中几乎是没有限制的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/78570.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/78570.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025.5.5总结

今日感悟:这假期就这样结束了,玩了一次滑板,打扫了一次租房,出去逛了一次街,看完了一本书,追了一部剧。既没有家人,也没有能一同畅饮的同学,更没有对象,显得确实有些孤独…

MySQL | DQL语句-连接查询

MySQL | DQL语句-连接查询 🪄个人博客:https://vite.xingji.fun 什么是连接查询 从一张表中查询数据称为单表查询。从两张或更多张表中联合查询数据称为多表查询,又叫做连接查询。什么时候需要使用连接查询? 比如这样的需求&…

Vite简单介绍

Vite 是一个现代化的前端构建工具,由 Vue.js 的创始人 Evan You 开发,旨在提供更快的开发体验和更高效的构建流程。它的名字来源于法语单词“vite”,意为“快速”,这也反映了它的核心优势——极速的冷启动和热模块替换&#xff08…

C语言-回调函数

回调函数 通过函数指针调用函数,而这个被调用的函数称为回调函数 回调函数是C语言中一种强大的机制,允许将函数作为参数传递给其他函数,从而在特定时机由后者调用。它的核心在于函数指针的使用 以下是回调函数的使用例子 先创建好一个函数…

启发式算法-禁忌搜索算法

禁忌搜索是一种可以用于解决组合优化问题的启发式算法,通过引入记忆机制跳出局部最优,避免重复搜索。该算法从一个初始解开始,通过邻域搜索策略来寻找当前解的邻域解,并在邻域解中选择一个最优解作为下一次迭代的当前解&#xff0…

Python 整理3种查看神经网络结构的方法

1. 网络结构代码 import torch import torch.nn as nn# 定义Actor-Critic模型 class ActorCritic(nn.Module):def __init__(self, state_dim, action_dim):super(ActorCritic, self).__init__()self.actor nn.Sequential(# 全连接层,输入维度为 state_dim&#xf…

Linux 查询CPU飙高的原因

获取进程ID ps -efgrep xxxx查询占用最高的线程ID top -Hp 线程ID线程ID 转 16进制数 printf 0x%x\n 线程ID基于jstack工具 跟踪堆栈定位代码位置 jstack 进程ID | grep 16禁止线程ID -A 20

Oracle OCP认证考试考点详解083系列09

题记: 本系列主要讲解Oracle OCP认证考试考点(题目),适用于19C/21C,跟着学OCP考试必过。 41. 第41题: 题目 解析及答案: 关于应用程序容器,以下哪三项是正确的? A) 它可以包含单个…

GESP2024年3月认证C++八级( 第二部分判断题(1-5))

孙子定理参考程序&#xff1a; #include <iostream> #include <vector> using namespace std;// 扩展欧几里得算法&#xff1a;用于求逆元 int extendedGCD(int a, int b, int &x, int &y) {if (b 0) {x 1; y 0;return a;}int x1, y1;int gcd extende…

C 语言比较运算符:程序如何做出“判断”?

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ 在编写程序时,我们经常需要根据不同的条件来执行不同的代码。比如,如果一个分数大于 60 分,就判断为及格;如果用户的年龄小于 18 岁,就禁止访问某个内容等等。这些“判断”的核心,就依赖于程序能够比…

WITH在MYSQL中的用法

WITH 子句&#xff08;也称为公共表表达式&#xff0c;Common Table Expression&#xff0c;简称 CTE&#xff09;是 SQL 中一种强大的查询构建工具&#xff0c;它可以显著提高复杂查询的可读性和可维护性。 一、基本语法结构 WITH cte_name AS (SELECT ... -- 定义CTE的查询…

多序列比对软件MAFFT介绍

MAFFT(Multiple Alignment using Fast Fourier Transform)是一款广泛使用且高效的多序列比对软件,由日本京都大学的Katoh Kazutaka等人开发,最早发布于2002年,并持续迭代优化至今。 它支持从几十条到上万条核酸或蛋白质序列的快速比对,同时在准确率和计算效率之间提供灵…

APP 设计中的色彩心理学:如何用色彩提升用户体验

在数字化时代&#xff0c;APP 已成为人们日常生活中不可或缺的一部分。用户在打开一个 APP 的瞬间&#xff0c;首先映入眼帘的便是其色彩搭配&#xff0c;而这些色彩并非只是视觉上的装饰&#xff0c;它们蕴含着强大的心理暗示力量&#xff0c;能够潜移默化地影响用户的情绪、行…

Compose 中使用 WebView

在 Jetpack Compose 中&#xff0c;我们可以使用 AndroidView 组件来集成传统的 Android WebView。以下是几种实现方式&#xff1a; 基础 WebView 实现 Composable fun WebViewScreen(url: String) {AndroidView(factory { context ->WebView(context).apply {// 设置布局…

2025年01月03日美蜥(杭州普瑞兼职)二面

目录 为何 nginx 可以实现跨域请求&#xff0c;原理是什么为何 nodejs 可以实现跨域请求&#xff0c;原理是什么浏览器的请求头有哪些浏览器的响应头有哪些浏览器输入网址后发生什么http 协议和 https 有什么区别你的核心优势是什么浏览器缓存机制https 的加密机制tcp 的三次握…

如何选择合适的光源?

目录 工业相机光源类型全面指南 1. 环形光源及其变体 高角度环形光源 优点 缺点 典型应用场景 低角度环形光源&#xff08;暗场照明&#xff09; 优点 缺点 典型应用场景 2. 条形光源与组合照明系统 技术特点 组合条形光源 优点 缺点 典型应用场景 3. 同轴光源…

「OC」源码学习——对象的底层探索

「OC」源码学习——对象的底层探索 前言 上次我们说到了源码里面的调用顺序&#xff0c;现在我们继续了解我们上一篇文章没有讲完的关于对象的内容函数&#xff0c;完整了解对象的产生对于isa赋值以及内存申请的内容 函数内容 先把_objc_rootAllocWithZone函数的内容先贴上…

【C++指南】STL list容器完全解读(一):从入门到掌握基础操作

. &#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 文章目录 一、初识list容器1.1 什么是list&#xff1f;1.2 核心特性1.3 典型应用场景 二、核心成员函数…

labelimg快捷键

一、核心标注快捷键 ‌W‌&#xff1a;调出标注十字架&#xff0c;开始绘制矩形框&#xff08;最常用功能&#xff09;‌A/D‌&#xff1a;切换上一张(A)或下一张(D)图片&#xff0c;实现快速导航‌Del‌&#xff1a;删除当前选中的标注框 二、文件操作快捷键 ‌CtrlS‌&…

linux-文件操作

在 Linux 系统中&#xff0c;文件操作与管理是日常使用和系统管理的重要组成部分。下面将详细介绍文件的复制、移动、链接创建&#xff0c;以及文件查找、文本处理、排序、权限管理等相关知识。 一、文件的复制 在 Linux 里&#xff0c;cp 命令可用于复制文件或目录&#xff…