python之序列化模块

一、介绍

模块:别人写好的功能放在一个文件里
内置模块 : 安装python解释器的时候一起装上的
第三方模块、扩展模块 :需要自己安装
自定义模块 : 你写的py文件

序列化模块
  什么叫序列化?
    把一个数据类型转换成字符串、byets类型的过程就是序列化

  为什么要把一个数据类型序列化?
    {'name':'小明','sex':'male'}
    当你需要把一个数据类型存储在文件中
    当你需要把一个数据类型通过网络传输的时候

 

二、json序列化模块(转换成字符串类型)

json的优点

  • 所有的语言都通用,可以跨平台或跨语言进行数据交互
  • 把数据类型(字典,列表)转成字符串形式,可以直接读写文件
  • 转成的字符串都是以双引号的形式

缺点

  • 只支持非常少的数据类型
        只支持元组(会转成列表)、数字、字符串、列表、字典
  • 应用场景
        在网络操作中,以及多语言环境中,要传递字典、数字、字符串、列表等简单的数据类型的时候使用
  • 对数据类型的约束很苛刻
        字典的key必须是字符串或数字,但是如果key是数字,则会把数字转成字符串作为key
  • 中文的值dumps后是字节形式的字符串

序列化:

  • dumps(dic/list):dic/list --> str 序列化方法
  • loads(str):str --> dic/list 反序列化方法
  • dump(dic/lst,f):dic/list --> 文件 序列化方法
  • load(f):文件 --> dic/list 反序列化方法 多次dump进入文件中的数据load会报错
  • 参数:ensure_ascii=False 希望序列化的中文能以中文的形式被显示并且写到文件中
复制代码
import json

1 - 1、字典:
dic = {'name': '小明', 'sex': 'male'}
ret = json.dumps(dic)  # 序列化的过程:字典--->字符串
print(dic, type(dic))  # {'name': '小明', 'sex': 'male'} <class 'dict'>
print(ret, type(ret))  # {"name": "\u5c0f\u660e", "sex": "male"} <class 'str'>

d = json.loads(ret)  # 反序列化:字符串--->字典
print(d, type(d))  # {'name': '小明', 'sex': 'male'} <class 'dict'>

1 - 2、列表:
lst = [1, 2, 3, 4, 'aaa', 'bbb']
ret = json.dumps(lst)  # 序列化的过程:列表--->字符串
print(lst, type(lst))  # [1, 2, 3, 4, 'aaa', 'bbb'] <class 'list'>
print(ret, type(ret))  # [1, 2, 3, 4, "aaa", "bbb"] <class 'str'>

l = json.loads(ret)  # 反序列化的过程:字符串--->列表
print(l, type(l))  # [1, 2, 3, 4, 'aaa', 'bbb'] <class 'list'>

1 - 3、元组:会被转成列表的形式,且转不回来
t1 = (1, 2)
ret = json.dumps(t1)
print(ret, type(ret))  # [1, 2] <class 'str'>

t2 = json.loads(ret)
print(t2, type(t2))  # [1, 2] <class 'list'>

1 - 4、key为数字的字典:会把数字转成字符串作为key,且转不回来
dic = {'name': '小明', 1: (1, 2)}
ret = json.dumps(dic)
print(dic, type(dic))  # {'name': '小明', 1: (1, 2)} <class 'dict'>
print(ret, type(ret))  # {"name": "\u5c0f\u660e", "1": [1, 2]} <class 'str'>

d = json.loads(ret)
print(d, type(d))  # {'name': '小明', '1': [1, 2]} <class 'dict'>

1 - 5、单独的数字:无异常
a = 10
b = json.dumps(a)
print(b, type(b))  # 10 <class 'str'>

ret = json.loads(b)
print(ret, type(ret))  # 10 <class 'int'>

1 - 6、字符串(等于没转,只是把单引号变成双引号):
a = 'aa'
b = json.dumps(a)
print(b, type(b))  # "aa" <class 'str'>

ret = json.loads(b)
print(ret, type(ret))  # aa <class 'str'>

1 - 7、loads可以单独使用:
ret = '{"name": "hello", "sex": "male"}'
dic2 = json.loads(ret)  # 反序列化
print(dic2, type(dic2))  # {'name': 'hello', 'sex': 'male'} <class 'dict'>

1 - 8、dumps的参数ensure_ascii:把中文正常显示出来,并不是字节形式
dic = {'name': '小明', 'sex': 'male'}
str1_dic = json.dumps(dic, ensure_ascii=False)
str2_dic = json.dumps(dic)
print(str1_dic)  # {"name": "小明", "sex": "male"}
print(str2_dic)  # {"name": "\u5c0f\u660e", "sex": "male"}

1 - 9、json读写文件:
普通的读写:dumps、loads
简洁读写:dump、load

普通的读写:写入时先dumps,读出时先loads
dic = {'name': '小明', 'sex': 'male'}
str = json.dumps(dic)
with open('json_file', 'w', encoding='utf-8') as f:
    f.write(str)

with open('json_file', encoding='utf-8', mode='r') as f:
    content = f.read()
ret = json.loads(content)
print(ret)

读写方法:dump、load, 这两个方法是完全和文件打交道的
dump(内容, 文件句柄, ensure_ascii)

dic = {'name': '小明', 'sex': 'male'}
with open('json_file', encoding='utf-8', mode='w') as f:
    json.dump(dic, f, ensure_ascii=False)

load(文件句柄)

with open('json_file', encoding='utf-8', mode='r') as f:
    dic = json.load(f)
print(dic)

1 - 10、可以多次向一个文件中dump,但是不能多次load。
dic = {'name': '小明', 'sex': 'male'}
with open('json_file', encoding='utf-8', mode='w') as f:
    json.dump(dic, f, ensure_ascii=False)
    json.dump(dic, f, ensure_ascii=False)
    json.dump(dic, f, ensure_ascii=False)  # 可以多次dump

with open('json_file', encoding='utf-8', mode='r') as f:
    dic = json.load(f)  # 但是不能多次load。
print(dic)

总结:
一次dump,可以用load或者loads读出内容
多次dump,无论是load或者loads都会报错(但是其实可以用for循环读出)

1 - 11、多次向一个文件写入
def my_dumps(dic):
    with open('json_file', encoding='utf-8', mode='a') as f:
        dic_str = json.dumps(dic)
        f.write(dic_str + '\n')


dic1 = {'name': '小明', 'sex': 'male'}
dic2 = {'name': '晓东', 'sex': 'male'}
dic3 = {'name': '李三', 'sex': 'male'}
my_dumps(dic1)
my_dumps(dic2)
my_dumps(dic3)

with open('json_file', encoding='utf-8', mode='r') as f:
    for line in f:
        dic = json.loads(line.strip())
        print(dic)

1 - 12、json格式化
import json

# dumps
data = {'name': ['小明', '张三'], 'sex': 'male', 'age': 19}
json_dic = json.dumps(data, sort_keys=True, indent=4, separators=(',', ':'), ensure_ascii=False)
print(json_dic)

# dump
data = {'name': ['小明', '张三'], 'sex': 'male', 'age': 19}
with open('json_file', encoding='utf-8', mode='w') as f:
    json.dump(data, f, sort_keys=True, indent=4, ensure_ascii=False)

# sort_keys=True:按照ASCII排序(a-z)
# indent=4:设置缩进格数,每次换行空四个格
# separators=(',',':'):设置分隔符,假如在dic = {'a': 1, 'b': 2, 'c': 3}这行代码里可以看到冒号和逗号后面都带了个空格,
# 这也是因为Python的默认格式也是如此,如果不想后面带有空格输出,那就可以设置成separators=(',', ':'),
# 如果想保持原样,可以写成separators=(', ', ': ')。
# ensure_ascii=False:中文以中文形式显示
复制代码

 

三、pickle序列化模块(换成byets类型)

应用场景:

  • pickle模块实现了基本的数据序列和反序列化,和json的功能类似。
  • 通过pickle模块的序列化操作我们能够将程序中运行的对象信息保存到文件中去,永久存储,也可以简单的将字符进行序列化
  • 通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象,也可以将字符进行反序列化。
  • 和json不同的是:json 更适合跨语言 可以处理字符串,基本数据类型;pickle是python专有,更适合处理复杂类型的序列化

具体应用:

  • dumps 和loads 用于python对象和字符串间的序列化和反序列化
  • pickle.dumps 和json.dumps功能一样,但是以字节对象形式返回封装的对象
  • pickle.loads和json.loads功能一样,从字节对象中读取被封装的对象,并返回
复制代码
2 - 1、dumps、loads
import pickle

dic = {'name': '小明', 'sex': 'male', 1: ('a', 'b')}
ret = pickle.dumps(dic)  # 序列化的过程:字典--->bytes
print(ret, type(ret))  # b'\x80\x03}q\x00(X\x04\x00\'<class 'bytes'>

dic2 = pickle.loads(ret)  # 反序列化:bytes--->字典
print(dic2, type(dic2))  # {'name': '小明', 'sex': 'male', 1: ('a', 'b')} <class 'dict'>


class Course():
    def __init__(self, name):
        self.name = name


python = Course('python')
ret = pickle.dumps(python)  # 序列化的过程:对象--->bytes
print(ret)  # b'\x80\x03c__main__\nCourse\nq\x00)\x00pythonq\x04sb.'

p = pickle.loads(ret)  # 反序列化的过程:bytes--->对象
print(p)  # <__main__.Course object at 0x0000028FE9583AC8>
print(p.name)  # python

# 读写文件的方法dump和load
with open('pickle', mode='wb') as f:
    pickle.dump(python, f)

with open('pickle', mode='rb') as f1:
    print(pickle.load(f1))

pickle:dump、load
    操作文件文件必须以b模式进行操作
    在load的时候
    如果这个要被load的内容所在的类不在内存中,会报错 ** ** *
    pickle支持多次dump和多次load(需要异常处理)

import pickle


class Fruit:
    def __init__(self, name):
        self.name = name


apple = Fruit('苹果')
banana = Fruit('香蕉')


def my_dump(fruit):
    with open('pickle', 'ab') as f:
        pickle.dump(fruit, f)


my_dump(apple)
my_dump(banana)

with open('pickle', 'rb') as f:
    while True:
        try:
            content = pickle.load(f)
            print(content.name)
        except EOFError:
            break
复制代码

 

posted @   我用python写Bug  阅读(471)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示