序列化: 将 xxx数据类型 转化为 字符串 的过程 -> 序列化后的字符串外面是单引号里面是双引号

序列化的作用: 因为在网络传输的时候只能传输字符串转码后的bytes类型,所以如果想传输xxx数据类型的数据,首先要先序列化xxx数据类型的数据得到字符串类型的数据,然后将字符串转换成 bytes 类型再进行传输

反序列化: 将 字符串 转化为 xxx数据类型 的过程



1. json 模块

  • 只有 数字、字符串、列表、字典、元组、布尔值、None 能够通过 json 转化为字符串

  • json.dumps(int/float/str/list/dict/tuple) -> 序列化 -> 返回值: 字符串

import json

dic = {'k1': 1, 'k2': 2, 'k3': 3}

s_json = json.dumps(dic)

print(repr(s_json))  # '{"k1": 1, "k3": 3, "k2": 2}'

  • json.loads(str) -> 反序列化 -> 返回值: xxx数据类型

import json

str_j = '{"k1": 1, "k3": 3, "k2": 2}'

s_json = json.loads(str_j)

print(s_json)  # {'k1': 1, 'k2': 2, 'k3': 3}

  • json.dump(int/float/str/list/dict/tuple, 文件句柄) -> 序列化 -> 将序列化后的字符串写入文件里

import json

lis = [1, 2, 3, 4, '中文']
f = open('serialization.txt', 'w', encoding='utf-8')
json.dump(lis, f)
f.close()

# serialization.txt 里的内容

[1, 2, 3, 4, "\u4e2d\u6587"]

  • json.dump(int/float/str/list/dict/tuple, 文件句柄, ensure_ascii=False) -> 序列化 -> 将序列化后的字符串写入文件里 -> ensure_ascii=False 默认值为 True 如果为 True 中文会以 bytes 类型显示(上面例子)(但是不会影响反序列化,反序列化出来的还是中文),如果为 False 按中文显示

import json

lis = [1, 2, 3, 4, '中文']
f = open('serialization.txt', 'w', encoding='utf-8')
json.dump(lis, f, ensure_ascii=False)
f.close()

# 加了 ensure_ascii=False 后 serialization.txt 里的内容

[1, 2, 3, 4, "中文"]

  • json.load(文件句柄) -> 反序列化 -> 从文件中读取字符串然后进行反序列化

# 加了 ensure_ascii=False 后 serialization.txt 里的内容

[1, 2, 3, 4, "\u4e2d\u6587"]

import json

f = open('serialization.txt', 'r', encoding='utf-8')
f_lis = json.load(f)

print(f_lis)  # [1, 2, 3, 4, '中文']
f.close()

  • 注意: json.dump() 和 json.load() 只能一次性写入 和 一次性读出

  •  一行一行的写入的方法

import json

lis = [{'k': '111'}, {'k2': '111'}, {'k3': '111'}]

f = open('serialization.txt', 'w', encoding='utf-8')
for i in lis:
    s_json = json.dumps(i)
    f.write(s_json + '\n')

f.close()

# serialization.txt 里的内容

{"k": "111"}
{"k2": "111"}
{"k3": "111"}

  • 一行一行的读取的方法

import json

f = open('serialization.txt', 'r', encoding='utf-8')
for i in f:
    s_json = json.loads(i.strip())
    print(s_json)

f.close()

# serialization.txt 里的内容

{"k": "111"}
{"k2": "111"}
{"k3": "111"}

  • 格式化输出

    • sort_keys: 是否按 key 排序
    • indent: 按几个空格缩进
    • separators: 按 xxx 进行分隔
    • ensure_ascii: 将 bytes 类型转化为中文显示

import json

data = {'username': ['李华', '二愣子'], 'sex': 'male', 'age': 16}
json_dic2 = json.dumps(data, sort_keys=True, indent=2, separators=(',', ':'), ensure_ascii=False)
print(json_dic2)

# 输出结果

{
  "age":16,
  "sex":"male",
  "username":[
    "李华",
    "二愣子"
  ]
}

2. pickle 模块

  • 所有的Python数据类型都可以转换为字符串

  • pickle 序列化的内容只有 Python 能理解

  • 部分反序列化要依赖 Python 代码

  • 序列化出来的是 bytes类型 所以都要以 bytes类型 读出或写入文件

  • pickle.dumps(python中的数据类型) -> 序列化 -> 返回值: bytes 类型

import pickle

dic = {'k1': 1, 'k2': 2, 'k3': 3}
p_str = pickle.dumps(dic)
print(p_str)  # b'\x80\x03}q\……'

  • pickle.loads(pickle序列化后的bytes类型) -> 反序列化 -> 返回值: xxx数据类型

import pickle

dic = {'k1': 1, 'k2': 2, 'k3': 3}
p_str = pickle.dumps(dic)

p_dic = pickle.loads(p_str)
print(p_dic) # {'k3': 3, 'k1': 1, 'k2': 2}

  • pickle.dump(python中的数据类型, 文件句柄) -> 序列化 -> 将序列化后的 bytes类型 以 bytes类型 写入文件里 -> 所写入的文件内容是乱码但是不会影响反序列化操作

import pickle

dic = {'k1': 1, 'k2': 2, 'k3': 3}

f = open('serialization.txt', 'wb')

pickle.dump(dic, f)

# serialization.txt 里的内容

�}q

  • pickle.load(文件句柄) -> 反序列化 ->  以 bytes类型方式从文件中读取字符串然后进行反序列化

import pickle

f = open('serialization.txt', 'rb')

p_dic = pickle.load(f)

print(p_dic)  # {'k3': 3, 'k2': 2, 'k1': 1}

# serialization.txt 里的内容

�}q

  • pickle.dump() 和 pickle.load() 可以分次写入或读取

import pickle

f = open('serialization.txt', 'wb')
pickle.dump({'k1': 1, 'k2': 2}, f)
pickle.dump({'k3': 3, 'k4': 4}, f)

f = open('serialization.txt', 'rb')
p_dic1 = pickle.load(f)  # {'k1': 1, 'k2': 2}
p_dic2 = pickle.load(f)  # {'k4': 4, 'k3': 3}

print(p_dic1)
print(p_dic2)

3. shelve 模块

  • 序列化句柄,直接使用句柄操作,非常方便

  • 序列化 -> 不用手动创建文件,序列化成功后会自动生成相关的文件

import shelve

f = shelve.open('shelve_file')  # 生成 shelve_file 的名字的相关文件

f['key'] = {'k1': 1, 'k2': 2}  # 直接对句柄操作就可以存入数据

f.close()


  • 反序列化 -> 从相关文件中获取数据

import shelve

f = shelve.open('shelve_file')

f['key'] = {'k1': 1, 'k2': 2}

existing = f['key']  # 取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错

print(existing) # {'k2': 2, 'k1': 1}

f.close()

  • writeback=True -> 在序列化完成后可以修改被序列化的数据类型

# 没加 writeback=True

import shelve

f = shelve.open('shelve_file')

f['key'] = {'k1': 1, 'k2': 2}

f['key']['k3'] = 3

existing = f['key']

print(existing) # {'k2': 2, 'k1': 1}

f.close()

# 加了 writeback=True

import shelve

f = shelve.open('shelve_file', writeback=True)

f['key'] = {'k1': 1, 'k2': 2}

f['key']['k3'] = 3

existing = f['key']

print(existing)  # {'k1': 1, 'k2': 2, 'k3': 3}

f.close()