Python学习之——序列化与反序列化

  • yaml & json & xml
    • yaml
    • json
      • Python自带Json库
    • xml
    • 一个综合示例
  • pickle & msgpack & marshal
    • pickle
    • msgpack
    • marshal
  • 自定义导出py文件
    • 一个导出py文件的示例

yaml & json & xml

YAML & JSON &XML 如何选择

yaml

Python的PyYAML模块详解

pip install pyyaml
import yaml# 自定义 Loader 类
class SafePersonLoader(yaml.SafeLoader):pass# 定义一个示例类
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return f"Person(name='{self.name}', age={self.age})"# 自定义序列化方法
def person_representer(dumper, person):# 自定义标签!Personreturn dumper.represent_mapping('!Person', {'name': person.name, 'age': person.age})# 自定义反序列化方法
def person_constructor(loader, node):fields = loader.construct_mapping(node, deep=True)return Person(**fields)class YamlUtil:def __init__(self):# 添加Person类实例的序列化方法yaml.add_representer(Person, person_representer)# 注册自定义标签!Person对应的反序列化方法SafePersonLoader.add_constructor('!Person', person_constructor)def dump_file(self, data, file_path):with open(file_path, "w", encoding="utf-8") as fp:yaml.dump(data, fp, default_flow_style=False)def dump_str(self, data):return yaml.dump(data)def load_file(self, file_path):with open(file_path, "r", encoding="utf-8") as fp:return yaml.load(fp, Loader=SafePersonLoader)def load_str(self, data):return yaml.load(data)def dump_obj_str(self, obj):return yaml.dump(obj)def dump_obj_file(self, obj, file_path):with open(file_path, "w", encoding="utf-8") as fp:yaml.dump(obj, fp, default_flow_style=False)def load_obj_str(self, yaml_str):return yaml.load(yaml_str, Loader=SafePersonLoader)def load_obj_file(self, file_path):with open(file_path, "r", encoding="utf-8") as fp:return yaml.load(fp, Loader=SafePersonLoader)if __name__ == "__main__":# 1.yaml的dump和loadyaml_util = YamlUtil()test_data = {"name": "test","age": 18,"ids": [1, 2, 3, [1, 2, 3, 4]],}yaml_util.dump_file(test_data, "./TestYaml.yaml")yaml_data = yaml_util.load_file("./TestYaml.yaml")print(yaml_data)# 自定义对象的dump和loadperson = Person("test", 18)yaml_str = yaml_util.dump_obj_str(person)print(yaml_str)yaml_util.dump_obj_file(person, "./TestYamlObj.yaml")person_new1 = yaml_util.load_obj_str(yaml_str)print(person_new1)person_new2 = yaml_util.load_obj_file("./TestYamlObj.yaml")print(person_new2)

json

一文看懂Python类型数据JSON序列化

python的dict和json数据有什么区别?

区别

  • Python的dict是一种数据结构,JSON是一种数据格式。
  • dict的key可以是任意可hash对象,json只能是字符串。{(1,2):1} 在python里是合法的,因为tuple是hashable type; {[1,2]:1} 在python里TypeError: unhashable “list”
  • 形式上有些相像,但json是纯文本的,无法直接操作。
  • dict字符串用单引号,json强制规定双引号。
  • dict里可以嵌套tuple, json里只有array。 json.dumps({1:2}) 的结果是 {“1”:2}, json.dumps((1,2)) 的结果是[1,2]
  • json: true|false|null ; dict:True|False|None

联系

  • dict 存在于内存中,可以被序列化成 json 格式的数据(string),之后这些数据就可以传输或者存储了。

Json数据类型和Python数据类型的对应关系如下:

  • Python 编码为 Json 类型转换对应表
PythonJson
dictobject
list, tuplearray
strstring
int, float, int- & float-derived Enumsnumber
Truetrue
Falsefalse
Nonenull
  • Json 解码为 Python 类型转换对应表:
JsonPython
objectdict
arraylist
stringstr
number (int)int
number (real)float
trueTrue
falseFalse
nullNone

Python自带Json库

Python自带Json库用于序列化和反序列化,主要包含了dumps, loads, dump和load四种方法,其作用分别如下所示:

json.dump	将Python对象按照JSON格式序列化到文件中
json.dumps	将Python对象处理成JSON格式的字符串json.load	将文件中的JSON数据反序列化成对象
json.loads	将字符串的内容反序列化成Python对象

很多python数据类型,如set, datetime,自定义的类等不能够直接通过dumps来序列化,可以通过如下两种方法解决

  1. 通过数据类型转换函数实现
  2. 通过继承JSONEncoder和JSONDecoder类实现

测试示例

# _*_ coding: UTF-8 _*_import json
from datetime import datetime# 定义一个示例类
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return f"Person(name='{self.name}', age={self.age})"def custom_dump_func(obj):if isinstance(obj, set):return {"class_name": "set","data": list(obj)}elif isinstance(obj, datetime):return {"class_name": "datetime","data": obj.strftime("%Y/%m/%d %H:%M:%S")}elif isinstance(obj, Person):return {"class_name": "Person","data": {"name": obj.name,"age": obj.age}}raise TypeErrordef custom_load_func(dct):if "class_name" in dct:if dct["class_name"] == "set":return set(dct["data"])elif dct["class_name"] == "datetime":return datetime.strptime(dct["data"], "%Y/%m/%d %H:%M:%S")elif dct["class_name"] == "Person":return Person(dct["data"]["name"], dct["data"]["age"])return dctclass CustomEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, set):return {"class_name": "set","data": list(obj)}elif isinstance(obj, datetime):return {"class_name": "datetime","data": obj.strftime("%Y/%m/%d %H:%M:%S")}elif isinstance(obj, Person):return {"class_name": "Person","data": {"name": obj.name,"age": obj.age}}return json.JSONEncoder.default(self, obj)class CustomDecoder(json.JSONDecoder):def __init__(self, *, object_hook=None, parse_float=None,parse_int=None, parse_constant=None, strict=True,object_pairs_hook=None):super().__init__(object_hook=self.object_hook, parse_float=parse_float,parse_int=parse_int, parse_constant=parse_constant, strict=strict,object_pairs_hook=object_pairs_hook)def object_hook(self, o):if "class_name" in o:if o["class_name"] == "set":return set(o["data"])elif o["class_name"] == "datetime":return datetime.strptime(o["data"], "%Y/%m/%d %H:%M:%S")elif o["class_name"] == "Person":return Person(o["data"]["name"], o["data"]["age"])return oclass JsonUtil:def dump_file(self, data, file_path, dump_func=None, cls=None, indent=4):with open(file_path, "w", encoding="utf-8") as fp:json.dump(data, fp, default=dump_func, cls=cls, indent=indent)def dump_str(self, data, dump_func=None, cls=None, indent=4):return json.dumps(data, default=dump_func, cls=cls, indent=indent)def load_file(self, file_path, load_func=None, cls=None):with open(file_path, "r", encoding="utf-8") as fp:return json.load(fp, object_hook=load_func, cls=cls)def load_str(self, data, load_func=None, cls=None):return json.loads(data, object_hook=load_func, cls=cls)if __name__ == "__main__":json_util = JsonUtil()test_dict = {"x": 1,"y": 2,"z": 3,"set": {"apple", "banana", "orange"},"datetime": datetime.now(),"person": Person("test", 18)}json_str1 = json_util.dump_str(test_dict, dump_func=custom_dump_func)print(json_str1)json_util.dump_file(test_dict, "./TestJson.json", dump_func=custom_dump_func)json_dict1 = json_util.load_str(json_str1, load_func=custom_load_func)print(json_dict1)json_dict2 = json_util.load_file("./TestJson.json", load_func=custom_load_func)print(json_dict2)json_str2 = json_util.dump_str(test_dict, cls=CustomEncoder)print(json_str2)json_util.dump_file(test_dict, "./TestJson2.json", cls=CustomEncoder)json_dict3 = json_util.load_str(json_str2, cls=CustomDecoder)print(json_dict3)json_dict4 = json_util.load_file("./TestJson2.json", cls=CustomDecoder)print(json_dict4)

xml

Python XML 解析

一个综合示例

import yaml
import json
# import xml
import xmltodictdef collect_subclasses(cls):"""使基类能够自动收集所有子类。"""cls.subclasses = {}def __init_subclass__(subclass, **kwargs):super(cls, subclass).__init_subclass__(**kwargs)cls.subclasses[subclass.__name__] = subclassdef get_subclass(cls, subcls_name):return cls.subclasses.get(subcls_name)cls.__init_subclass__ = classmethod(__init_subclass__)cls.get_subclass = classmethod(get_subclass)return cls# 自定义 Loader 类
class SafePersonLoader(yaml.SafeLoader):pass@collect_subclasses
class BaseClass:def __init__(self, **kwargs):self.dump_func = {"yaml": self.dump_to_yaml,"json": self.dump_to_json,"xml": self.dump_to_xml,}self.load_func = {"yaml": self.load_from_yaml,"json": self.load_from_json,"xml": self.load_from_xml,}def to_dict(self):return self.__dict__def from_dict(self, data_dict):self.__dict__.update(data_dict)def serialize(self, type_name="yaml"):dump_func = self.dump_func.get(type_name)if dump_func is None:raise ValueError(f"Invalid type_name: {type_name}")data_dict = self.to_dict()return dump_func(data_dict)def unserialize(self, data_str, type_name="yaml"):load_func = self.load_func.get(type_name)if load_func is None:raise ValueError(f"Invalid type_name: {type_name}")data_dict = load_func(data_str)class_name = data_dict["class_name"]sub_cls = BaseClass.get_subclass(class_name)sub_obj = sub_cls()sub_obj.from_dict(data_dict)return sub_objdef dump_to_yaml(self, data_dict):return yaml.dump(data_dict)def load_from_yaml(self, data_str):data_dict = yaml.load(data_str, Loader=SafePersonLoader)return data_dictdef dump_to_json(self, data_dict):return json.dumps(data_dict)def load_from_json(self, data_str):return json.loads(data_str)def dump_to_xml(self, data_dict):if len(data_dict) != 1:data_dict = {"root": data_dict}return xmltodict.unparse(data_dict, pretty=True)def load_from_xml(self, data_str):data_dict = xmltodict.parse(data_str)if data_dict["root"]:data_dict = data_dict["root"]return data_dictclass SubClass1(BaseClass):def __init__(self, **kwargs):super().__init__(**kwargs)self.name = "test"self.age = 18self.ids = [1, 2, 3, [1, 2, 3, 4]]def to_dict(self):return {"class_name": self.__class__.__name__,"name": self.name,"age": self.age,"ids": self.ids,}def from_dict(self, data_dict):self.name = data_dict["name"]self.age = data_dict["age"]self.ids = data_dict["ids"]class SubClass2(BaseClass):passif __name__ == "__main__":# 1.子类收集# 获取 SubClass1subclass1 = BaseClass.get_subclass("SubClass1")print(subclass1)# 2.自定义序列化与反序列化的对象# 序列化后发送obj = SubClass1()obj_str = obj.serialize(type_name="json")# 接收后反序列化obj_new = BaseClass().unserialize(obj_str, type_name="json")print(obj_new)

pickle & msgpack & marshal

pickle

The Python pickle Module: How to Persist Objects in Python
Python的pickle模块详解

msgpack

官网:https://msgpack.org/
Python版本:https://github.com/aviramha/ormsgpack/tree/master
使用实例:MessagePack简介及使用:一种有效的二进制序列化格式

marshal

官网:marshal — Internal Python object serialization
使用实例:Python 中的 marshal 模块

自定义导出py文件

一个导出py文件的示例

# -*- coding: utf-8 -*-
import os
import jsonclass TestExport():EXPORT_START = '# ----------------export-begin----------------'EXPORT_END = '# ----------------export-end----------------\n'LINE_INDENT = '    'def __init__(self):self._dump_handler = {bytes: self._dump_bytes,str: self._dump_string,list: self._dump_list,dict: self._dump_dict,}def dump_to_str(self, py_data):dump_data = "{}\n{}\n{}".format(self.EXPORT_START,'export_data = %s' % self._dumps(py_data),self.EXPORT_END)return dump_datadef dump_to_file(self, py_data, file_path):abs_file_path = os.path.abspath(file_path)file_dir = os.path.dirname(abs_file_path)try:# exist_ok=True 表示如果目录已存在则不会抛出异常os.makedirs(file_dir, exist_ok=True)except Exception as e:print(f"创建目录 {file_dir} 时出错: {e}")old_file_content = ""# 检查文件是否存在if os.path.exists(abs_file_path):try:# 指定编码方式为 utf-8with open(abs_file_path, "r", encoding="utf-8") as fp:old_file_content = fp.read()except Exception as e:print(f"读取文件 {abs_file_path} 时出错: {e}")dump_data = self.dump_to_str(py_data)start_index = old_file_content.find(self.EXPORT_START)end_index = old_file_content.find(self.EXPORT_END) + len(self.EXPORT_END)if start_index != -1 and end_index != -1:# 提取 self.EXPORT_START 之前和 self.EXPORT_END 之后的内容prefix = old_file_content[:start_index]suffix = old_file_content[end_index:]dump_data = prefix + dump_data + suffixelse:# 若标记不全,直接追加原文件内容dump_data += old_file_contentwith open(abs_file_path, "w", encoding="utf-8") as fp:fp.write(dump_data)def _dumps(self, in_data):dump_func = self._dump_handler.get(type(in_data), self._dump_default)return dump_func(in_data)def _dump_default(self, in_data):return str(in_data)def _dump_string(self, in_str):return json.dumps(in_str, ensure_ascii=False)def _dump_bytes(self, in_bytes):return json.dumps(in_bytes.decode("utf-8"), ensure_ascii=False)def _dump_list(self, in_list):if not in_list:return "[]"ret = "[\n"for v in in_list:v_str = self._dumps(v)# 如果v_str中含有\n, 说明有嵌套if "\n" in v_str:v_str += ","for line in v_str.split("\n"):ret += "{}{}\n".format(self.LINE_INDENT, line)else:ret += "{}{},\n".format(self.LINE_INDENT, v_str)ret += "]"return retdef _dump_dict(self, in_dict):if not in_dict:return "{}"ret = "{\n"keyList = sorted(in_dict.keys())for k in keyList:v = in_dict[k]k_str = self._dumps(k)v_str = self._dumps(v)# 如果v_str中含有\n, 说明有嵌套if "\n" in v_str:sub_v_str = ""for line in v_str.split("\n"):sub_v_str += "{}{}\n".format(self.LINE_INDENT, line)# 去掉第一个INDENT_STR和最后一个\nsub_v_str = sub_v_str[len(self.LINE_INDENT):-1]ret += "{}{}: {},\n".format(self.LINE_INDENT, k_str, sub_v_str)else:ret += "{}{}: {},\n".format(self.LINE_INDENT, k_str, v_str)ret += "}"return retif __name__ == "__main__":test_dict = {"a_list": [1, 2, 3, [1, 2, 3, 4], {"x": "x1"}],"b_str": "b","d": 4,"c_dict": {"c": 3,},}test_export = TestExport()test_export.dump_to_file(test_dict, "./TestExport.py")

导出示例
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/91565.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/91565.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/91565.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式之代理模式:掌控对象访问的优雅之道

代理模式:掌控对象访问的优雅之道 引言:设计模式的重要性 在软件开发中,设计模式是解决常见问题的可复用方案,它们如同建筑师的蓝图,为开发者提供了经过验证的最佳实践。在23种经典设计模式中,代理模式因其…

sqli-labs靶场通关笔记:第18-19关 HTTP头部注入

第18关 User-Agent注入登录正确的用户名密码,它会将User-Agent的信息回显到页面上。猜测UA头可能存在注入点。利用bp抓包,在UA头后面加一个单引号,发现报错了。观察报错信息,显示nearxx,admin),推测后面应该还有两个参…

基于按键开源MultiButton框架深入理解代码框架(三)(指针的深入理解与应用)

文章目录3、分析代码3.3 按键的插入3.4 按键的删除3.5 继续分析状态机核心理解4、写在最后的总结5、思想感悟篇6、慈悲不渡自绝人3、分析代码 3.3 按键的插入 // Button handle list headstatic Button* head_handle NULL;/*** brief Start the button work, add the handle…

ACOUSLIC-AI挑战报告:基于低收入国家盲扫超声数据的胎儿腹围测量|文献速递-医学影像算法文献分享

Title题目ACOUSLIC-AI challenge report: Fetal abdominal circumferencemeasurement on blind-sweep ultrasound data from low-income countriesACOUSLIC-AI挑战报告:基于低收入国家盲扫超声数据的胎儿腹围测量01文献速递介绍胎儿生长受限(FGR&#xf…

集群聊天服务器各个类进行详解

1.dh.h类定义概要类名: MySQL功能: 简化MySQL的连接、查询和更新操作,提供接口给上层应用使用。成员变量private:MYSQL *_conn;_conn:指向MYSQL结构体的指针,用于代表数据库连接实例。由mysql_init()初始化&#xff0c…

电缆安全双保险:不止防盗,更能防触电的塔能智慧照明守护方案

城市照明、地下车库以及园区路灯所涉及的电缆安全问题,向来都是运维管理方面颇为棘手的难题。在传统的运维管理模式之下,电缆一旦被盗,那么所造成的影响可不小,一方面会带来直接的经济损失,另一方面还极有可能因为线路…

Leetcode刷题营第二十九,三十题:二叉树的中序以及后序遍历

94.二叉树的中序遍历 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root [1,null,2,3] 输出:[1,3,2]示例 2: 输入:root [] 输出:[]示例 3: 输入&#x…

Rabbitmq Direct Exchange(直连交换机)可以保证消费不被重复消费吗,可以多个消费者,但是需要保证同一个消息,不会被投递给多个消费者

在 RabbitMQ 中,默认情况下,不能保证消息不被重复消费,但可以通过 队列绑定方式 消费者竞争机制 来确保 同一消息只被一个消费者处理。以下是几种可行的方案:方案 1:单队列 竞争消费者模式(默认行为&…

常用的OTP语音芯片有哪些?

唯创知音在 OTP 语音芯片有着26年的历史,有着丰富的技术积累与产品迭代历程。1999 年,唯创知音在广州成立,彼时便开始在电子领域积极探索。2000 年,公司敏锐捕捉到语音芯片行业的发展潜力,正式进军该领域。经过数年技术…

分布式光伏发电系统中的“四可”指的是什么?

在分布式光伏电站规模爆发式增长的今天,“看不见、管不住、调不动”的难题却成为行业痛点。如何让散布各处的光伏电站真正成为稳定高效的“绿色能量站”?2025年《分布式光伏发电开发建设管理办法》大型工商业项目(≥6MW)明确要求具…

健康管理系统新趋势:AI + 物联网如何重塑健康管理

一、传统健康管理的痛点与变革之必然长久以来,我们熟悉的健康管理方式存在明显局限:数据孤岛严重:体检报告在抽屉里沉睡,健身手环数据仅存于手机,不同医疗机构信息互不相通,个人健康信息犹如碎片散落各处。…

git基本操作【GIT-2】

git基本操作初始化一个仓库(repository)、开始或停止跟踪(track)文件、暂存(stage)或提交(commit)更改如何配置 Git 来忽略指定的文件和文件模式、如何迅速而简单地撤销错误操作、如…

【数据准备】——深度学习.全连接神经网络

目录 1 数据加载器 1.1 构建数据类 1.1.1 Dataset类 1.1.2 TensorDataset类 1.2 数据加载器 2 数据加载案例 2.1 加载csv数据集 2.2 加载图片数据集 2.3 加载官方数据集 2.4 pytorch实现线性回归 1 数据加载器 分数据集和加载器2个步骤~ 1.1 构建数据类 1.1.1 Dat…

健康生活,从细节开始

健康生活,从细节开始在当今快节奏的生活中,健康逐渐成为人们关注的焦点。拥有健康的身体,才能更好地享受生活、追求梦想。那么,如何才能拥有健康呢?这就需要我们从生活中的点滴细节入手,培养良好的生活习惯…

javax.servlet.http.HttpServletResponse;API导入报错解决方案

javax.servlet.http.HttpServletResponse;API导入报错解决方案与Postman上传下载文件验证 1. 主要错误:缺少 Servlet API 依赖 错误信息显示 javax.servlet.http 包不存在。这是因为你的项目缺少 Servlet API 依赖。 解决方案: 如果你使用的是 Maven&…

reids依赖删除,但springboot仍然需要redis参数才能启动

背景:项目需要删除redis。我删除完项目所有配置redis的依赖,启动报错。[2025-07-17 15:08:37:561] [DEBUG] [restartedMain] DEBUG _.s.w.s.H.Mappings - [detectHandlerMethods,295] [] - o.s.b.a.w.s.e.BasicErrorController:{ [/error]}: error(HttpS…

【前端】CSS类命名规范指南

在 CSS 中,合理且规范的 class 命名格式对项目的可维护性和协作效率至关重要。以下是主流的 class 命名规范和方法论:一、核心命名原则语义化命名:描述功能而非样式 ✅ .search-form(描述功能)❌ .red-text&#xff08…

C++网络编程 4.UDP套接字(socket)编程示例程序

以下是基于UDP协议的完整客户端和服务器代码。UDP与TCP的核心区别在于无连接特性&#xff0c;因此代码结构会更简单&#xff08;无需监听和接受连接&#xff09;。 UDP服务器代码&#xff08;udp_server.cpp&#xff09; #include <iostream> #include <sys/socket.h&…

King’s LIMS:实验室数字化转型的智能高效之选

实验室数字化转型不仅是技术升级&#xff0c;更是管理理念和工作方式的革新。LIMS系统作为这一转型的核心工具&#xff0c;能够将分散的实验数据转化为可分析、可复用的资产&#xff0c;为科研决策提供支持&#xff1b;规范检测流程&#xff0c;减少人为干预&#xff0c;确保结…

【力扣 中等 C】97. 交错字符串

目录 题目 解法一 题目 待添加 解法一 bool isInterleave(char* s1, char* s2, char* s3) {const int len1 strlen(s1);const int len2 strlen(s2);const int len3 strlen(s3);if (len1 len2 ! len3) {return false;}if (len1 < len2) {return isInterleave(s2, s1,…