序列化

From https://www.liaoxuefeng.com/

在程序运行的过程中,所有的变量都是在内存中,比如,定义一个dict:
d = dict(name='Bob', age=20, score=88)

可以随时修改变量,比如把name改成'Bill',但是一旦程序结束,变量所占用的内存就被操作系统全部回收。如果没有把修改后的'Bill'存储到磁盘上,下次重新运行程序,变量又被初始化为'Bob'

我们把变量从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。

序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。

反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。

Python提供两个模块来实现序列化:cPicklepickle。这两个模块功能是一样的,区别在于cPickle是C语言写的,速度快,pickle是纯Python写的,速度慢,跟cStringIOStringIO一个道理。用的时候,先尝试导入cPickle,如果失败,再导入pickle

try:import cPickle as pickle
except ImportError:import pickle 

首先,我们尝试把一个对象序列化并写入文件:

>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d) "(dp0\nS'age'\np1\nI20\nsS'score'\np2\nI88\nsS'name'\np3\nS'Bob'\np4\ns." 

pickle.dumps()方法把任意对象序列化成一个str,然后,就可以把这个str写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object:

>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close() 

看看写入的dump.txt文件,一堆乱七八糟的内容,这些都是Python保存的对象内部信息。

当我们要把对象从磁盘读到内存时,可以先把内容读到一个str,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load()方法从一个file-like Object中直接反序列化出对象。我们打开另一个Python命令行来反序列化刚才保存的对象:

>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close() >>> d {'age': 20, 'score': 88, 'name': 'Bob'} 

变量的内容又回来了!

当然,这个变量和原来的变量是完全不相干的对象,它们只是内容相同而已。

Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

JSON

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:

JSON类型 Python类型
{} dict
[] list
"string" 'str'或u'unicode'
1234.56 int或float
true/false True/False
null None

Python内置的json模块提供了非常完善的Python对象到JSON格式的转换。我们先看看如何把Python对象变成一个JSON:

>>> import json
>>> d = dict(name='Bob', age=20, score=88) >>> json.dumps(d) '{"age": 20, "score": 88, "name": "Bob"}' 

dumps()方法返回一个str,内容就是标准的JSON。类似的,dump()方法可以直接把JSON写入一个file-like Object

要把JSON反序列化为Python对象,用loads()或者对应的load()方法,前者把JSON的字符串反序列化,后者从file-like Object中读取字符串并反序列化:

>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{u'age': 20, u'score': 88, u'name': u'Bob'} 

有一点需要注意,就是反序列化得到的所有字符串对象默认都是unicode而不是str。由于JSON标准规定JSON编码是UTF-8,所以我们总是能正确地在Python的strunicode与JSON的字符串之间转换。

JSON进阶

Python的dict对象可以直接序列化为JSON的{},不过,很多时候,我们更喜欢用class表示对象,比如定义Student类,然后序列化:

import jsonclass Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score s = Student('Bob', 20, 88) print(json.dumps(s)) 

运行代码,毫不留情地得到一个TypeError

Traceback (most recent call last):...
TypeError: <__main__.Student object at 0x10aabef50> is not JSON serializable 

错误的原因是Student对象不是一个可序列化为JSON的对象。

如果连class的实例对象都无法序列化为JSON,这肯定不合理!

别急,我们仔细看看dumps()方法的参数列表,可以发现,除了第一个必须的obj参数外,dumps()方法还提供了一大堆的可选参数:

https://docs.python.org/2/library/json.html#json.dumps

这些可选参数就是让我们来定制JSON序列化。前面的代码之所以无法把Student类实例序列化为JSON,是因为默认情况下,dumps()方法不知道如何将Student实例变为一个JSON的{}对象。

可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为Student专门写一个转换函数,再把函数传进去即可:

def student2dict(std):return { 'name': std.name, 'age': std.age, 'score': std.score } print(json.dumps(s, default=student2dict)) 

这样,Student实例首先被student2dict()函数转换成dict,然后再被顺利序列化为JSON。

不过,下次如果遇到一个Teacher类的实例,照样无法序列化为JSON。我们可以偷个懒,把任意class的实例变为dict

print(json.dumps(s, default=lambda obj: obj.__dict__))

因为通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。也有少数例外,比如定义了__slots__的class。

同样的道理,如果我们要把JSON反序列化为一个Student对象实例,loads()方法首先转换出一个dict对象,然后,我们传入的object_hook函数负责把dict转换为Student实例:

def dict2student(d):return Student(d['name'], d['age'], d['score']) json_str = '{"age": 20, "score": 88, "name": "Bob"}' print(json.loads(json_str, object_hook=dict2student)) 

运行结果如下:

<__main__.Student object at 0x10cd3c190> 

打印出的是反序列化的Student实例对象。

小结

Python语言特定的序列化模块是pickle,但如果要把序列化搞得更通用、更符合Web标准,就可以使用json模块。

json模块的dumps()loads()函数是定义得非常好的接口的典范。当我们使用时,只需要传入一个必须的参数。但是,当默认的序列化或反序列机制不满足我们的要求时,我们又可以传入更多的参数来定制序列化或反序列化的规则,既做到了接口简单易用,又做到了充分的扩展性和灵活性。

转载于:https://www.cnblogs.com/if-then/p/7355335.html

python序列化-复习相关推荐

  1. 【面试复习】Python基础复习

    [面试复习]Python基础复习 前言 相信一些学习python的朋友找不到一些python的的朋友找不到相对应的python面经,所以博主就推荐大家可以去牛客上面看看哦,各种大厂面经和习题哦! 地址 ...

  2. 太牛了 Python期末复习总结,提高成绩必备回家过个开心年

    Python期末复习之语法 将用一张思维导图的形式来展示python的基础语法. Python期末复习之运算符 Python语言支持以下类型的运算符: 算术运算符 比较(关系)运算符 赋值运算符 逻辑 ...

  3. python序列化和反序列化ppt_老生常谈Python序列化和反序列化

    通过将对象序列化可以将其存储在变量或者文件中,可以保存当时对象的状态,实现其生命周期的延长.并且需要时可以再次将这个对象读取出来.Python中有几个常用模块可实现这一功能. pickle模块 存储在 ...

  4. Python 序列化 pickle/cPickle模块

    Python 序列化 pickle/cPickle模块 2013-10-17 Posted by yeho Python序列化的概念很简单.内存里面有一个数据结构,你希望将它保存下来,重用,或者发送给 ...

  5. python序列化持久化需要注意的一个问题

    python序列化一个对象的时候如果需要写入文件,一定要记得打开方式需要增加b选项否则fwrite会默认以为是要进行String的写入而失败. 同样读取文件的时候也需要加入b选项以示binary 转载 ...

  6. python编写自定义函数判断n1-n2范围内的素数_【每日道代码题001】- PYTHON基础复习...

    问题001-1:请对输入三个整数a,b,c,判断能否以它们为三个边长构成三角形.若能,输出YES和面积,否则输出NO a = float(input()) b = float(input()) c = ...

  7. Python 速效复习汇总(新手慎用)二

    Python 速效复习汇总 jieba库 常用分词函数 示例 文件 打开与关闭 读和写相关方法 PIL 库 一. Image 类 图像读取和创建 常用属性 序列图像操作方法 图像转换和保存方法 图像旋 ...

  8. python 基础复习二

    这里写自定义目录标题 python 基础复习二 1.数据类型 2.数据的应用 3.数据的转换 总结 python 基础复习二 1.数据类型 最常用的数据类型有三种--字符串(str).整数(int)和 ...

  9. 11. python入门复习教程之命名空间与作用域,再谈异常,标准库,持久化与序列化

    如果你学习 python 一段时间之后,会经常碰到命名空间,作用域 这两个名词,接下来咱们就从这两个名词开始入手,展开这篇博客. 命名空间与作用域 命名空间是指对象所处的位置,命名二字一般指的是变量名 ...

  10. python序列化和反序列化

    通过将对象序列化可以将其存储在变量或者文件中,可以保存当时对象的状态,实现其生命周期的延长.并且需要时可以再次将这个对象读取出来.Python中有几个常用模块可实现这一功能. pickle模块 存储在 ...

最新文章

  1. 从Python调用外部命令
  2. 关于Jboss/Tomcat/Jetty的JNDI定义123
  3. Linux系统时间与RTC时间【转】
  4. LCM在Kernel中的代码分析
  5. Variable Assembly Language可变汇编语言
  6. 发布:NetBeans IDE 8.1 Beta
  7. 编译安装PHP-7.2.8
  8. 搜狗高速浏览器打开网页没有声音怎么办
  9. Skip-Thought Vector —— 跳跃思维句表示
  10. cocos2d pod_cocos2d 和 cocos3d的版本问题
  11. Mybatis, 实现一对多
  12. 【05】CC - 格式
  13. 【ROS学习笔记】(十一)launch启动文件的使用方法
  14. 掌握好这几点方法学习Linux,一定比别人更快入门运维!
  15. 了解和熟悉数据库相关知识
  16. 给闪讯加装路由器的一个简单方法
  17. 大数据难吗?如何快速掌握大数据开发技能
  18. homeassistant添加米家空调伴侣
  19. 量化金融分析AQF(1):股票概述
  20. js:数组转链表,链表转数组

热门文章

  1. OSPF虚链路技术原理与注意点
  2. MySQL优化详解(四)——MySQL缓存设置
  3. google 浏览器使用的一些小技巧
  4. 新人如何使用git加入到团队开发中
  5. 基于汇编的 C/C++ 协程 - 实现
  6. android 内存泄漏问题【转】
  7. Go编程笔记(28)
  8. 囚徒困境(博弈论的诡计)
  9. CSS样式切换技巧 - 动态更换网页色彩皮肤
  10. navicat for mysql提示_Navicat for MySQL使用教程: MYSQL的提示操作和技巧