Loading

json与pickle模块

序列化与反序列化

序列化指的是把内存的数据类型转换成一个特定格式的内容,该格式的内容可用于存储或者传输给其他平台使用。

  • 内存中的数据--->序列化--->特定的格式的字符串或bytes类型。
  • 特定的格式字符串或bytes类型--->反序列化--->内存中的数据。

序列化的用途

序列化得到的特定格式内容有两种用途

  • 1.可用于存储。
  • 2.传输给其他平台使用 => 跨平台数据交互。

针对用途1的格式:

  • 可以是一种专用的格式,只有Python可以识别 => pickle 格式

针对用途2的格式:

  • 应该是一种通用、能够被所用语言识别的格式 => json 格式

json模块

  • json.dumps():序列化
import json
res = json.dumps([1,'abc',True])
print(res,type(res))

[1, "abc", true] <class 'str'> 单引号变双引号

# 将序列化的内容写入文件
with open('test.txt',mode='wt',encoding='utf-8') as f:
    res = json.dumps([1,'abc',True])
    f.write(res)
  • json.loads():反序列化
li = json.loads(res)
print(li,type(li))
[1, 'abc', True] <class 'list'>
# 双引号会变为单引号

# 将写入文件的内容读出并反序列化
with open('test.txt',mode='r',encoding='utf-8') as f:
    res1 = json.loads(f.read())
    print(res1,type(res1))

[1, 'abc', True] <class 'list'>

注意:在python解释器2.7与3.6之后都可以json.loads(bytes类型),但唯独3.5不可以。

>>> import json
>>> json.loads(b'{"a":111}')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/linhaifeng/anaconda3/lib/python3.5/json/__init__.py", line 312, in loads
    s.__class__.__name__))
TypeError: the JSON object must be str, not 'bytes'

json.dump(date,file_obj):将传进去的date序列化为JSON格式后写入文件对象file_obj。

>>> import json
>>> with open('a.txt',mode='wt',encoding='utf-8') as f:
...     json.dump([True,None,"abc"],f)

[true, null, "abc"]

json.load(file_obj):读取文件内容将其反序列化,返回反序列化后的内容。

>>> with open('a.txt',mode='rt',encoding='utf-8') as f:
...     res = json.load(f)
...
>>> res
[True, None, 'abc']

json格式序列化后与原数据类型的区别:

原数据格式 JSON
True true
False false
None null
'abc' "abc"

JSON序列化默认支持的对象和类型:

Python JSON
dict object
list, tuple array
str string
int, float, int 和 float 派生的枚举 number
True true
False false
None null

反序列化支持的对象和类型:

JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None

pickle模块:

模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。

pickle 模块并不安全。你只应该对你信任的数据进行unpickle操作,构建恶意的 pickle 数据来在解封时执行任意代码是可能的。绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。考虑使用 hmac 来对数据进行签名,确保数据没有被篡改。

pickle.dumps():序列化。

import pickle

res = pickle.dumps({1,2,3,4,5,'a'}
print(res,type(res))
# b'\x80\x04\x95\x13\x00\x00\x00\x00\x00\x00\x00\x8f\x94(K\x01K\x02K\x03K\x04K\x05\x8c\x01a\x94\x90.' <class 'bytes'>

pickle.loads():反序列化。

res1 = pickle.loads(res)
print(res1,type(res1))
# {1, 2, 3, 4, 5, 'a'} <class 'set'>

pickle.dump(obj,file):将对象 obj 封存以后的对象写入已打开的file文件对象。

with open('a.txt',mode='wb') as f:
    pickle.dump({'k1':None,"k2":'abc'},f)

pickle.load(f):从已打开的文件 中读取封存后的对象,重建其中特定对象的层次结构并返回。

with open('a.txt',mode='rb') as f:
    res = pickle.load(f)
    print(res)
    
{'k1': None, 'k2': 'abc'}

注意:pickle序列化后的内容为bytes类型,所以打开文件必须要为b模式。

  • Python2与Python3的pickle兼容性问题。
# coding:utf-8
import pickle

with open('a.pkl',mode='wb') as f:
    # 一:在python3中执行的序列化操作如何兼容python2
    # python2不支持protocol>2,默认python3中protocol=4
    # 所以在python3中dump操作应该指定protocol=2
    pickle.dump('你好啊',f,protocol=2)

with open('a.pkl', mode='rb') as f:
    # 二:python2中反序列化才能正常使用
    res=pickle.load(f)
    print(res)
  • Pickle的问题和所有其他编程语言特有的序列化问题一样,就是它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系。

json与pickle区别

  • JSON 是一个文本序列化格式(它输出 unicode 文本,尽管在大多数时候它会接着以 utf-8 编码),而 pickle 是一个二进制序列化格式;
  • JSON 是可以直观阅读的,而 pickle 不是;
  • JSON是可互操作的,在Python系统之外广泛使用,而pickle则是Python专用的;
  • 默认情况下,JSON 只能表示 Python 内置类型的子集,不能表示自定义的类;但 pickle 可以表示大量的 Python 数据类型(可以合理使用 Python 的对象内省功能自动地表示大多数类型,复杂情况可以通过实现 specific object APIs 来解决)。
  • 不像pickle,对一个不信任的JSON进行反序列化的操作本身不会造成任意代码执行漏洞。

参考文档:

https://docs.python.org/zh-cn/3/library/json.html?highlight=json#module-json

posted @ 2020-12-14 21:37  吃了好多肉  阅读(113)  评论(0编辑  收藏  举报