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 的对象,jsonPython 内置的数据类型对应如下:

JSON类型Python类型
{}dict
[]list
"string"'str' 或 u'unicode'
3.14int 或 float
true / falseTrue / False
nullNone

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

标签:Python,对象序列化,pickle,json
0
投稿

猜你喜欢

  • Python使用shutil模块实现文件拷贝

    2021-02-01 14:46:28
  • python中urllib模块用法实例详解

    2022-02-05 13:23:33
  • 如何使用Vue3设计实现一个Model组件浅析

    2024-04-27 15:57:19
  • MySQL查看和修改时区的方法

    2024-01-15 05:42:33
  • 使用Python来开发Markdown脚本扩展的实例分享

    2023-06-02 06:48:06
  • 图文详解python安装Scrapy框架步骤

    2022-02-11 15:02:47
  • python爬虫把url链接编码成gbk2312格式过程解析

    2023-04-26 21:00:10
  • Python+OpenCV实现表面缺陷检测

    2021-10-17 21:25:21
  • 网页中的平衡、对比、连贯和留白

    2008-11-24 12:11:00
  • Oracle10g 安装方法

    2009-06-19 17:50:00
  • 关于ASP eof与bof 区别分析

    2011-03-11 11:14:00
  • 浅谈python函数之作用域(python3.5)

    2021-09-22 05:49:42
  • OpenCV Python实现拼图小游戏

    2021-07-30 18:10:34
  • Python实现微信好友的数据分析

    2023-10-21 15:54:20
  • PHP实现的MD5结合RSA签名算法实例

    2023-11-08 05:03:00
  • Python实现简单的文件传输与MySQL备份的脚本分享

    2024-01-21 04:44:44
  • Python正则表达式常用函数总结

    2023-07-27 12:37:41
  • php删除二维数组中的重复值方法

    2024-06-05 09:51:20
  • MySQL timestamp自动更新时间分享

    2024-01-22 11:48:21
  • 简单的Python2.7编程初学经验总结

    2021-03-18 01:27:11
  • asp之家 网络编程 m.aspxhome.com