Python序列化和反序列化

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

pickle模块

存储在变量中

dumps(obj)返回存入的字节

  1. dic = {'age': 23, 'job': 'student'}
  2. byte_data = pickle.dumps(dic)
  3. # out -> b'\x80\x03}q\x00(X\x03\x00\x00\...'
  4. print(byte_data)

读取数据

数据以字节保存在了byte_data变量中,需要再次使用的时候使用loads函数就行了。

  1. obj = pickle.loads(byte_data)
  2. print(obj)

存储在文件中

也可以存在文件中,使得对象持久化。使用的是dumpload函数,注意和上面的区别,少了s。由于pickle写入的是二进制数据,所以打开方式需要以wbrb的模式。

  1. # 序列化
  2. with open('abc.pkl', 'wb') as f:
  3. dic = {'age': 23, 'job': 'student'}
  4. pickle.dump(dic, f)
  5. # 反序列化
  6. with open('abc.pkl', 'rb') as f:
  7. aa = pickle.load(f)
  8. print(aa)
  9. print(type(aa)) # <class 'dict'>

序列化用户自定义对象

假如我写了个类叫做Person

  1. class Person:
  2. def __init__(self, name, age, job):
  3. self.name = name
  4. self.age = age
  5. self.job = job
  6. def work(self):
  7. print(self.name, 'is working...')

pickle当然也能写入,不仅可以写入类本身,也能写入它的一个实例

  1. # 将实例存储在变量中,当然也能存在文件中
  2. a_person = Person('abc', 22, 'waiter')
  3. person_abc = pickle.dumps(a_person)
  4. p = pickle.loads(person_abc)
  5. p.work()
  6. # 将类本身存储在变量中,loads的时候返回类本身,而非它的一个实例
  7. class_Person = pickle.dumps(Person)
  8. Person = pickle.loads(class_Person)
  9. p = Person('Bob', 23, 'Student')
  10. p.work()
  11. # 下面这个例子演示的就是将类存储在文件中
  12. # 序列化
  13. with open('person.pkl', 'wb') as f:
  14. pickle.dump(Person, f)
  15. # 反序列化
  16. with open('person.pkl', 'rb') as f:
  17. Person = pickle.load(f)
  18. aa = Person('gg', 23, '6')
  19. aa.work()

json模块

pickle可以很方便地序列化所有对象。不过json作为更为标准的格式,具有更好的可读性(pickle是二进制数据)和跨平台性。是个不错的选择。

json使用的四个函数名和pickle一致。

序列化为字符串

  1. dic = {'age': 23, 'job': 'student'}
  2. dic_str = json.dumps(dic)
  3. print(type(dic_str), dic_str)
  4. # out: <class 'str'> {"age": 23, "job": "student"}
  5. dic_obj = json.loads(dic_str)
  6. print(type(dic_obj), dic_obj)
  7. # out: <class 'dict'> {'age': 23, 'job': 'student'}

可以看到,dumps函数将对象转换成了字符串。loads函数又将其恢复成字典。

存储为json文件

也可以存储在json文件中

  1. dic = {'age': 23, 'job': 'student'}
  2. with open('abc.json', 'w', encoding='utf-8') as f:
  3. json.dump(dic, f)
  4. with open('abc.json', encoding='utf-8') as f:
  5. obj = json.load(f)
  6. print(obj)

存储自定义对象

还是上面的Person对象。如果直接序列化会报错

  1. aa = Person('Bob', 23, 'Student')
  2. with open('abc.json', 'w', encoding='utf-8') as f:
  3. json.dump(aa, f) # 报错

Object of type 'Person' is not JSON serializable此时dump函数里传一个参default就可以了,这个参数接受一个函数,这个函数可以将对象转换为字典。

写一个就是了

  1. def person2dict(person):
  2. return {'name': person.name,
  3. 'age': person.age,
  4. 'job': person.job}

这样返回的就是一个字典了,对象实例有个方法可以简化这一过程。直接调用实例的__dict__。例如

  1. print(aa.__dict) # {'name': 'Bob', 'age': 23, 'job': 'Student'}

很方便。

同时在读取的时候load出来的是一个字典,再转回对象就可,同样需要一个object_hook参数,该参数接收一个函数,用于将字典转为对象。

  1. def dict2person(dic):
  2. return Person(dic['name'], dic['age'], dic['job'])

于是完整的程序应该写成下面这样

  1. with open('abc.json', 'w', encoding='utf-8') as f:
  2. json.dump(aa, f, default=person2dict)
  3. with open('abc.json', encoding='utf-8') as f:
  4. obj = json.load(f, object_hook=dict2person)
  5. print(obj.name, obj.age, obj.job)
  6. obj.work()

由于可以使用__dict__代替person2dict函数,再使用lambda函数简化。

  1. with open('abc.json', 'w', encoding='utf-8') as f:
  2. json.dump(aa, f, default=lambda obj: obj.__dict__)

以上是存储到文件,存储到变量也是类似操作。

不过就我现在所学,不知道如何像pickle一样方便的将我们自定义的类本身使用json序列化,或许要用到其他扩展函数。以后用到了再说。

shelve模块

还有一个模块,不太常用,通常使用一个open就好。shelve以键值对的形式存储数据。

  1. with shelve.open('aa') as f:
  2. f['person'] = {'age': 23, 'job': 'student'}
  3. f['person']['age'] = 44 # 这里试图改变原来的年龄23
  4. f['numbers'] = [i for i in range(10)]
  5. with shelve.open('aa') as f:
  6. person = f['person']
  7. print(person) # {'age': 23, 'job': 'student'}
  8. nums = f['numbers']
  9. print(nums) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

文件不要有后缀名,在windows下会生成aa.bak, aa.dat, aa.dir三个文件(有点多)。其中bak和dir文件是可以查看的(貌似两个文件内容一样)在下面这个例子中生成这样的数据。

  1. 'person', (0, 44)
  2. 'numbers', (512, 28)

允许写回--writeback

有个细节,我们读取键person时候,发现age还是23岁,f['person']['age'] = 44后并没有变成44。下面的写法

  1. with shelve.open('aa', writeback=True) as f:
  2. dic = {'age': 23, 'job': 'student'}
  3. f['person'] = dic
  4. dic['age'] = 44
  5. f['person'] = dic

相当于赋值了两次,这种方法是可以改变值的。

默认情况下直接使用f['person']改变其中的值之后,不会更新已存储的值,也就是没有把更新写回到文件,即使是文件被close后。如果有此需要,在open函数中添加一个参数writeback=True。再次运行下看看年龄就被改变了。

写入自定义对象

依然使用上面的Person对象

  1. with shelve.open('aa') as f:
  2. f['class'] = Person
  3. # 写入类本身
  4. with shelve.open('aa') as f:
  5. Person = f['class']
  6. a = Person('Bob', 23, 'Student')
  7. a.work()

上面的例子说明shelve也可以序列化类本身。当然序列化实例肯定可以。

  1. with shelve.open('aa') as f:
  2. a = Person('God', 100, 'watch')
  3. f['class'] = a
  4. with shelve.open('aa') as f:
  5. god = f['class']
  6. god.work()

注意,由于我们使用with open打开,故不用写close语句,此模块是有close函数的,如果不是with方法打开的一定要记得主动close。


by @sunhaiyu

2017.6.27

Python序列化和反序列化的更多相关文章

  1. python序列化与反序列化(json与pickle)

    在python中,序列化可以理解为将python中对象的编码格式转换为json(pickle)格式的字符串,而反序列化可以 理解为将json(pickle)格式的字符串转换为python中对象的编码格 ...

  2. Python—序列化和反序列化模块(json、pickle和shelve)

    什么是序列化 我们把对象(或者变量)从内存中变为可存储或者可传输的过程称为序列化.在python中为pickling,在其他语言中也被称之为serialization,marshalling,flat ...

  3. Python 序列化与反序列化

    序列化是为了将内存中的字典.列表.集合以及各种对象,保存到一个文件中(字节流).而反序列化是将字节流转化回原始的对象的一个过程. json库 序列化:json.dumps() 反序列化:json.lo ...

  4. python序列化与反序列化(json、pickle)-(五)

    1.什么是序列化&反序列化? 序列化:将字典.列表.类的实例对象等内容转换成一个字符串的过程. 反序列化:将一个字符串转换成字典.列表.类的实例对象等内容的过程 PS:Python中常见的数据 ...

  5. python 序列化和反序列化

    概念 序列化: 将对象的状态信息转换为可以存储或传输的形式的过程.就是把对象转换成字符串的过程 反序列化: 把字符串转换成python可以识别的数据类型对象的过程 应用 #数据存储 #网络传输 模块 ...

  6. python 序列化,反序列化

    附: pickle 有大量的配置选项和一些棘手的问题.对于最常见的使用场景,你不需要去担心这个,是如果你要在一个重要的程序中使用pickle 去做序列化的话,最好去查阅一下官方文档. https:// ...

  7. Python序列化与反序列化-json与pickle

    Python序列化与反序列化-json与pickle 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.json的序列化方式与反序列化方式 1>.json序列化 #!/usr ...

  8. Python序列化和反序列化vsJSON

    # -*- coding: utf-8 -* """没有嵌套类的类 author: Jill usage: """ import json ...

  9. Python库:序列化和反序列化模块pickle介绍

    1 前言 在“通过简单示例来理解什么是机器学习”这篇文章里提到了pickle库的使用,本文来做进一步的阐述. 通过简单示例来理解什么是机器学习 pickle是python语言的一个标准模块,安装pyt ...

随机推荐

  1. php中引用&的一个小实例

    在百度知道上碰到一段关于php的引用符&的代码,对于初学都来说还是很考验理解分析能力的,把代码和自己的分析贴上来作一个备份,也与大家共勉. 代码片段: $arr =array(1,2,3,4) ...

  2. MySQL数据库web维护客户端管理工具

    TreeSoft数据库管理系统使用JAVA开发,采用稳定通用的springMVC +JDBC架构,实现基于WEB方式对 MySQL,Oracle,PostgreSQL 等数据库进行维护管理操作. 功能 ...

  3. ASP.NET Core配置Kestrel 网址Urls

    ASP.NET Core中如何配置Kestrel Urls呢,大家可能都知道使用UseUrls() 方法来配置. 今天给介绍全面的ASP.NET Core 配置 Urls,使用多种方式配置Urls.让 ...

  4. EJB系列 - 消息与MDB

    什么是消息 松散耦合的异步通信过程 1. 面向消息的中间件(MOM): 消息发送者称为生产者; 存储消息的位置称为目的地; 接受消息的组件称为消费者 2. 消息模型:  a. 点对点:目的地成为队列, ...

  5. [ABP框架]动态web Api的拦截用法。

    先进行配置 首先这种需求,一般发生在APP端,我们给APP,不会给所有项目系统的接口给他们用.我们系统有200个接口,但是APP的需求只会用20个.那么这个需求也就应运而生了. 以上为API文件夹中为 ...

  6. AngularJS服务和路由

    colnplie     网页加载的出现一次 link     元素每次改变的时候 **$watch** 监听列表     $scope.$watch("name",functio ...

  7. 分页插件Jpages的使用

    项目原因需要前端做分页表格,之前做了一个ul的分页效果,但是感觉自己写还是造轮子了,今天网上看到Jpqges插件就试了下,感觉平时使用挺方便的,写一下自己的使用过程. 先上套图,下载下来就2个js和1 ...

  8. Unity 游戏框架搭建 (三) MonoBehaviour单例的模板

      上一篇文章讲述了如何设计C#单例的模板.也随之抛出了问题: 如何设计接收MonoBehaviour生命周期的单例的模板? 如何设计? 先分析下需求:   1.约束脚本实例对象的个数.   2.约束 ...

  9. 微信开发之获取jsapi_ticket

    一.获取流程 1.获取 access_token 2.通过access_token换取 jsapi_ticket 3.签名算法 签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有 ...

  10. Android 动画——Frame Animation与Tween Animation

    很多手机应用的引导页都是动画的,添加动画后的应用画面会更加生动灵活,今天博主也学习了Android中Animation的使用,下面来总结下.  android中的Animation分为两种,一种是Fr ...