python进阶突破内置模块——数据序列化与格式

liftword1周前 (04-30)技术文章3

数据序列化是将数据结构或对象转换为可存储/传输格式的过程,反序列化则是逆向操作。Python 提供了多种工具来处理不同场景下的序列化需求。


一、核心内置模块

1.json模块

最常用的轻量级数据交换格式,适用于跨语言交互。

基础用法

import json

data = {
    "name": "Alice",
    "age": 30,
    "skills": ["Python", "SQL"]
}

# 序列化为字符串
json_str = json.dumps(data, indent=2) 

# 序列化到文件
with open("data.json", "w") as f:
    json.dump(data, f)

# 反序列化
loaded_data = json.loads(json_str)
with open("data.json", "r") as f:
    loaded_data = json.load(f)

进阶功能

  • 处理复杂对象:自定义序列化逻辑
from datetime import datetime

class User:
    def __init__(self, name, join_date):
        self.name = name
        self.join_date = join_date

def custom_encoder(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    elif isinstance(obj, User):
        return {"name": obj.name, "join_date": obj.join_date}
    raise TypeError("Type not serializable")

user = User("Bob", datetime.now())
json_str = json.dumps(user, default=custom_encoder, indent=2)

性能优化:使用 ujson 或 orjson 第三方库加速

2.pickle模块

Python 专用二进制序列化,支持几乎所有 Python 对象,但存在安全风险。

基础用法

import pickle

data = {"key": "value", "nums": [1, 2, 3]}

# 序列化到字节
bytes_data = pickle.dumps(data)

# 反序列化
loaded_data = pickle.loads(bytes_data)

# 文件操作
with open("data.pkl", "wb") as f:
    pickle.dump(data, f)

with open("data.pkl", "rb") as f:
    loaded_data = pickle.load(f)

注意事项

  • 安全警告:永远不要反序列化不可信来源的数据
  • 版本兼容性:不同 Python 版本的 pickle 文件可能不兼容
  • 自定义对象:需保证类定义在反序列化环境中可用

二、高级序列化场景

1. 处理复杂数据结构

循环引用处理

import json

data = {}
data["self_ref"] = data  # 循环引用

# 默认会报错,使用自定义处理
class CyclicEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, dict) and id(obj) in self.visited:
            return "<<循环引用>>"
        self.visited.add(id(obj))
        return super().default(obj)

encoder = CyclicEncoder()
encoder.visited = set()
json_str = encoder.encode(data)

2. 高性能二进制序列化

使用marshal(内置模块)

  • 专为 Python 字节码设计,性能极高
  • 但官方不保证跨版本兼容性
import marshal

data = {"a": 1, "b": [2, 3]}
bytes_data = marshal.dumps(data)
loaded_data = marshal.loads(bytes_data)

三、常用第三方库

1.msgpack

二进制格式,性能优于 JSON,跨语言支持。

import msgpack

data = {"name": "Charlie", "scores": [95, 88]}
packed = msgpack.packb(data)      # 序列化
unpacked = msgpack.unpackb(packed) # 反序列化

2.PyYAML

处理 YAML 格式,适合配置文件。

import yaml

config = """
database:
  host: localhost
  port: 3306
  users:
    - admin
    - guest
"""

data = yaml.safe_load(config)  # 安全加载
yaml_str = yaml.dump(data)     # 生成 YAML

3.protobuf

Google 的高效跨语言序列化方案。

// person.proto
syntax = "proto3";
message Person {
    string name = 1;
    int32 id = 2;
    repeated string emails = 3;
}
from person_pb2 import Person

person = Person(name="Alice", id=123)
person.emails.append("alice@example.com")
serialized = person.SerializeToString()  # 序列化

new_person = Person()
new_person.ParseFromString(serialized)   # 反序列化

四、性能对比与选型建议

格式/工具

可读性

速度

跨语言

适用场景

JSON

Web API、配置文件

Pickle

Python 内部数据持久化

MessagePack

很快

高性能网络通信

Protocol Buffers

极快

微服务通信、大数据存储

YAML

复杂配置文件

五、最佳实践

  1. 安全性优先
  • 永远不要使用 pickle 处理不可信数据
  • 使用 json.loads() 而非 eval() 解析 JSON
  1. 性能优化
  • 对大文件使用 json.load()/json.dump() 流式处理
  • 使用 orjson 替代标准 json 模块(性能提升3-10倍)
  1. 版本控制
  • 为序列化数据添加版本字段
{
    "version": "1.1",
    "data": {...}
}
  1. 处理日期时间
from datetime import datetime
from json import JSONEncoder

class DateTimeEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime):
            return obj.isoformat()
        return super().default(obj)

六、实战:自定义序列化协议

实现一个支持自定义类的序列化方案:

import json
from dataclasses import dataclass

@dataclass
class Product:
    id: int
    name: str
    price: float

class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Product):
            return {"__product__": True, "id": obj.id, "name": obj.name, "price": obj.price}
        return super().default(obj)

def custom_decoder(dct):
    if "__product__" in dct:
        return Product(dct["id"], dct["name"], dct["price"])
    return dct

# 使用
product = Product(1, "Laptop", 999.9)
json_str = json.dumps(product, cls=CustomEncoder)
loaded = json.loads(json_str, object_hook=custom_decoder)
print(type(loaded))  # <class '__main__.Product'>

掌握这些工具和技术后,您将能够:

  • 在不同场景选择最优序列化方案
  • 处理复杂对象的序列化需求
  • 优化大规模数据的处理性能
  • 构建安全的跨系统数据交换方案

相关文章

python进阶实战:如何使用自定义模块(包)?

有时,我们希望在py文件中导入其他py文件中的函数或类等功能,这样就可以将自己编写的代码进行重复使用,并且可以规范化积累自己的代码,成为自己代码学习的重要成果。当然,可以将这些模块化的代码共享出来,供...

必知必会!Python json模块全解析(python jsonpath-rw)

深入掌握Python json模块:从基础到实战的全面指南在当今数据驱动的时代,高效的数据处理与交换至关重要。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格...

9-Python自定义函数(python自定义一个函数)

1-概念在Python中,自定义函数是指由用户根据自身需求定义的函数。通过定义自己的函数,可以将代码组织成可重用的模块,提高代码的可读性和维护性。此外,函数还可以接受参数并返回结果,使得程序逻辑更加清...

Python import自定义模块报错、自定义异常、字符串处理、截取

一、python import自定义的模块报错问题现象:pycharm中运行一切正常,但是到命令行中(cmd命令行或pycharm的Terminal窗口)运行py文件,就会报错No module na...

Python的shutil模块:文件处理的得力助手

对话实录小白:(苦恼)我在Python中处理文件时,总是觉得自带的open函数不太够用,有没有更强大的工具呀?专家:(微笑)那你可不能错过shutil模块!它就像是文件处理的瑞士军刀,提供了大量便捷的...