Python 对象序列化与反序列化之pickle json详细解析
作者:忆想不到的晖 发布时间:2021-09-06 23:44:06
引言
将对象的状态信息转换为可以存储或传输的形式的过程叫作序列化
类似地从序列化后的数据转换成相对应的对象叫作 反序列化
本文介绍 Python
将对象序列化和反序化的两个模块
picklejson
pickle
pickle
# 序列化
In [19]: num = 66
In [20]: s = 'python'
In [21]: pi = 3.14
In [22]: li = [1, 2, 3]
In [27]: b_num = pickle.dumps(num)
In [28]: b_s = pickle.dumps(s)
In [29]: b_pi = pickle.dumps(pi)
In [30]: b_li = pickle.dumps(li)
In [31]: b_num
Out[31]: b'\x80\x03KB.'
In [32]: b_s
Out[32]: b'\x80\x03X\x06\x00\x00\x00pythonq\x00.'
In [33]: b_pi
Out[33]: b'\x80\x03G@\t\x1e\xb8Q\xeb\x85\x1f.'
In [34]: b_li
Out[34]: b'\x80\x03]q\x00(K\x01K\x02K\x03e.'
In [35]: type(b_li)
Out[35]: bytes
# 反序列化
In [47]: pickle.loads(b_num)
Out[47]: 66
In [48]: pickle.loads(b_s)
Out[48]: 'python'
In [49]: pickle.loads(b_pi)
Out[49]: 3.14
In [50]: li = pickle.loads(b_li)
In [51]: li
Out[51]: [1, 2, 3]
In [52]: type(li)
Out[52]: list
自定义的对象也能序列化
class User:
def __init__(self, name, sex):
self.name = name
self.sex = sex
In [38]: user = User('hui', '男')
In [39]: b_user = pickle.dumps(user)
In [40]: b_user
Out[40]: b'\x80\x03c__main__\nUser\nq\x00)\x81q\x01}q\x02(X\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00huiq\x04X\x03\x00\x00\x00sexq\x05X\x03\x00\x00\x00\xe7\x94\xb7q\x06ub.'
In [41]: type(b_user)
Out[41]: bytes
In [42]: user = pickle.loads(b_user)
In [43]: type(user)
Out[43]: __main__.User
In [44]: user.name
Out[44]: 'hui'
In [45]: user.sex
Out[45]: '男'
注意:pickle
序列化后数据都是字节(bytes)类型
pickle
也可以把对象序列化保存到文件,然后从文件反序化回对象。
import pickle
class User:
def __init__(self, name, sex):
self.name = name
self.sex = sex
user = User('ithui', '男')
f = open('user.txt', mode='wb')
pickle.dump(user, f)
f.close()
从文件反序化回对象
In [3]: f = open('user.txt', 'rb')
...: user = pickle.load(f)
...: f.close()
...:
In [4]: user
Out[4]: <__main__.User at 0x16c58ebef08>
In [5]: user.name
Out[5]: 'ithui'
In [6]: user.sex
Out[6]: '男'
pickle
模块虽然可以将对象序列化,但它只适用于 Python
语言,所以不方便数据交换。例如你将数据发给前端,js
则无法将数据转成自己想要的。
json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如 json
,因为 json
表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输进行数据交换。
json
字符串表示的对象就是 js
的对象,json
和 Python
内置的数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | 'str' 或 u'unicode' |
3.14 | int 或 float |
true / false | True / False |
null | None |
In [7]: import json
In [8]: info_dict = {
...: 'name': 'hui',
...: 'age': 22,
...: 'is_admin': True,
...: 'hobbies': ['下象棋', '写代码'],
...: 'other': None
...: }
In [9]: info_json = json.dumps(info_dict)
In [10]: info_json
Out[10]: '{
"name": "hui",
"age": 22,
"is_admin": true,
"hobbies": ["\\u4e0b\\u8c61\\u68cb", "\\u5199\\u4ee3\\u7801"],
"other": null
}'
# 对应的反序列化
In [16]: info_d = json.loads(info_json)
In [17]: info_d
Out[17]:
{'name': 'hui',
'age': 22,
'is_admin': True,
'hobbies': ['下象棋', '写代码'],
'other': None}
In [18]: type(info_d)
Out[18]: dict
看看自定义的类对象能不能 json
序列化
In [21]: import json
In [22]: class User:
...:
...: def __init__(self, name, sex):
...: self.name = name
...: self.sex = sex
...:
In [23]: user = User('ithui', '男')
In [24]: json.dumps(user)
TypeError: Object of type User is not JSON serializable
报错了,说 User
对象不能 json
序列化。有没有方法可以让自定义的对象可以转成 json
,肯定是有的。
大致思路就是先把User对象转成可以被 json
序列化的对象,例如 dict
等,然后再把可序列化的对象给 json
模块。
In [28]: def user2dict(obj):
...: return {'name': obj.name, 'sex': obj.sex}
...:
...:
In [29]: user = User('ithui', '男')
In [30]: user_dict = user2dict(user)
In [31]: user_dict
Out[31]: {'name': 'ithui', 'sex': '男'}
In [32]: user_json = json.dumps(user_dict)
In [33]: user_json
Out[33]: '{"name": "ithui", "sex": "\\u7537"}'
也可以在序列化的时候指定一个转换器,可选参数 default
就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为 User
专门写一个转换函数,再把函数传进去即可:
In [28]: def user2dict(obj):
...: return {'name': obj.name, 'sex': obj.sex}
...:
...:
In [34]: user_json = json.dumps(user, default=user2dict)
In [35]: user_json
Out[35]: '{"name": "ithui", "sex": "\\u7537"}'
这样虽然可以把自定义的类对象转换成 json
但是要为不同的类专门定制不同的转换器,重复又麻烦,因此想到利用的每个类的 __dict__
属性来序列化,它是一个 dict
对象,用来存储实例变量。也有少数例外,比如定义了 __slots__
的 class
In [36]: user.__dict__
Out[36]: {'name': 'ithui', 'sex': '男'}
In [41]: json.dumps(user.__dict__)
Out[41]: '{"name": "ithui", "sex": "\\u7537"}'
注意:如果是对象中的属性又嵌套另一个不能直接 json
序列化的对象,使用 __dict__
属性照样无法正常序列化。
尾语
✍ 用 Code 谱写世界,让生活更有趣。❤️
✍ 万水千山总是情,点赞再走行不行。❤️
✍ 码字不易,还望各位大侠多多支持。❤️
来源:https://blog.csdn.net/qq_43629857/article/details/120542441
猜你喜欢
- 两种方式以及效果:方式一,使用PIL.Image.blend方式:from PIL import Image, ImageDrawim =
- 使用本Activation code需要jetbrains-agent支持!插件Activation code:06KU174Y5C-eyJ
- 一、pip简介Pip 是安装python包的工具,提供了安装包,列出已经安装的包,升级包以及卸载包的功能。Pip 是对easy_instal
- 一、创建堆heapq有两种方式创建堆, 一种是使用一个空列表,然后使用heapq.heappush()函数把值加入堆中,另外一种就是使用he
- 1. rangerange是python内置的一个类,该类型表示一个不可改变(immutable)的数字序列,常常用于在for循环中迭代一组
- 一、绑定方法1.对象的绑定方法首先我们明确一个知识点,凡是类中的方法或函数,默认情况下都是绑定给对象使用的。下面,我们通过实例,来慢慢解析绑
- 此次主要介绍介绍在flask框架中如何集成swagger文档, 我们知道以前给同事提供接口文档主要是写一个文档, 当遇到频繁修改
- 前言本文给大家深入的解答了关于Python的11道基本面试题,通过这些面试题大家能对python进一步的了解和学习,下面话不多说,来看看详细
- python爬虫中使用urli库可以使用opener"发送多个请求,这些请求是能共享处理cookie的,小编之前也提过python
- 想不到大家都这么喜欢用python给女朋友挑钻石,所以我又写了个续。如果看过之前一篇用python挑钻石的文章,那么可以直接从箱线图开始读。
- 问题:在数据库脚本开发中,有时需要生成一堆连续数字或者日期,例如yearly report就需要连续数字做年份,例如daily report
- 本文实例讲述了Python扫描IP段查看指定端口是否开放的方法。分享给大家供大家参考。具体实现方法如下:#!/usr/local/bin/p
- 使用Django静态设置时,遇到很多问题,经过艰苦的Baidu, stack overflow, Django原档阅读,终于把静态图片给搞出
- sqrt()方法返回x的平方根(x>0)。语法以下是sqrt()方法的语法:import mathmath.sqrt( x
- 游戏截图动态演示源码分享state/tool.pyimport osimport jsonfrom abc import abstractm
- clone 一个新项目,发现导包的时候出错 …原因可能是 pycharm 的根目录设置不对。设置根目录的步骤 如下 :来源:https://
- 近期公司准备开发一个计费项目,数据库当然还是选用我最信赖的Oracle了。由于一部分基础数据在一台Win2000 Server的S
- MASK图像掩膜处理在图像操作中有时候会用到掩膜处理,如果使用遍历法掩膜图像ROI区域对于python来讲是很慢的,所以我们要找到一种比较好
- 操作系统:Ubuntu 17.04 64位MySQL版本:MySQL 5.7一、查看3306端口是否开放netstat -an|grep 3
- Updates(2019.8.14 19:53)吃饭前用这个方法实战了一下,吃完回来一看好像不太行:跑完一组参数之后,到跑下一组参数时好像没