12 · 文件 I/O 与序列化

12 · 文件 I/O 与序列化

导语:程序要「落地」,就离不开读写文件------把结果存成 CSV 给 Excel 打开,把数据存成 JSON 传给前端,把状态存成 pickle 下次接着用。这一篇讲清 Python 的文件读写、现代路径操作 pathlib,以及 CSV、JSON、pickle 三种序列化方式。

1. open 与 with 语句

读文件用 open(),配合 with 语句自动关闭:

python 复制代码
with open("data.txt", encoding="utf-8") as f:
    content = f.read()
    print(content)

with自动关闭文件 (即使中途出错),不用手动 f.close()。这是读写文件的标准姿势。

几种常用模式:

模式 含义 文件不存在时
"r" 只读(默认) 报错
"w" 写入(覆盖) 自动创建
"a" 追加 自动创建
"rb" 二进制读 报错
"wb" 二进制写 自动创建
python 复制代码
# 逐行读取(大文件推荐,省内存)
with open("data.txt", encoding="utf-8") as f:
    for line in f:
        print(line, end="")

# 写入
with open("out.txt", "w", encoding="utf-8") as f:
    f.write("第一行\n")
    f.write("第二行\n")

🚫 避坑 :读写文本 文件务必加 encoding="utf-8"。Windows 上默认编码可能是 GBK,不加会导致中文乱码或报错。"rb"/"wb" 用于图片、音频等二进制 文件,此时不要加 encoding

2. pathlib:现代路径操作

传统 os.path 用字符串拼路径,容易出错。pathlib 用面向对象的方式操作路径,是现代首选:

python 复制代码
from pathlib import Path

# 当前目录
base = Path(".") / "data"          # 用 / 拼接路径,直观
base.mkdir(exist_ok=True)          # 建目录,已存在不报错

file = base / "report.json"
file.write_text('{"ok": true}', encoding="utf-8")   # 直接写文本
print(file.exists())               # 输出:True
print(file.name)                   # 输出:report.json
print(file.suffix)                 # 输出:.json

# 遍历目录下所有 .txt 文件
for txt in Path(".").glob("*.txt"):
    print(txt)
  • Path / "子目录"/ 拼路径,跨平台。
  • read_text / write_text 一行搞定读写。
  • glob() 按模式匹配文件,exists()namesuffix 都是常用属性。

💡 转行速览pathlib 约等于 Java 的 java.nio.file.Path,把路径当对象而非字符串处理。

3. CSV 读写(csv 模块)

CSV 是「逗号分隔值」,Excel 和数据分析最通用的表格格式。用标准库 csv 模块:

python 复制代码
import csv

# 写入 CSV
rows = [
    ["订单号", "金额", "状态"],
    ["A001", "199.0", "已支付"],
    ["A002", "299.0", "待支付"],
]
with open("orders.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerows(rows)

# 读取 CSV
with open("orders.csv", encoding="utf-8") as f:
    reader = csv.DictReader(f)   # 用 DictReader,每行变成字典
    for row in reader:
        print(row["订单号"], row["金额"])
# 输出:
# A001 199.0
# A002 299.0

🚫 避坑 :写 CSV 时 open 要加 newline=""(尤其是 Windows),否则会多出空行。DictReader 用第一行做键,读起来比 reader 的下标更清晰,推荐。

4. JSON 序列化与反序列化

JSON 是互联网数据交换的标准,和 Python 字典几乎一一对应。四个核心函数:

函数 方向 说明
json.dumps(obj) 对象 → 字符串 序列化
json.loads(text) 字符串 → 对象 反序列化
json.dump(obj, f) 对象 → 文件 写文件
json.load(f) 文件 → 对象 读文件
python 复制代码
import json

order = {
    "order_id": "A20260829001",
    "customer": {"name": "赵敏", "city": "杭州"},
    "total": 9797.0,
}

# 序列化成字符串(ensure_ascii=False 让中文不转成 \uXXXX)
text = json.dumps(order, ensure_ascii=False, indent=2)
print(text)
# 输出:
# {
#   "order_id": "A20260829001",
#   "customer": {
#     "name": "赵敏",
#     "city": "杭州"
#   },
#   "total": 9797.0
# }

# 反序列化回字典
data = json.loads(text)
print(data["customer"]["name"])  # 输出:赵敏

# 直接写/读文件
with open("order.json", "w", encoding="utf-8") as f:
    json.dump(order, f, ensure_ascii=False, indent=2)

with open("order.json", encoding="utf-8") as f:
    loaded = json.load(f)
print(loaded["total"])           # 输出:9797.0

💡 提示ensure_ascii=False 让中文保持原样、可读;indent=2 让输出带缩进、更美观。但注意 :JSON 里没有「元组」「日期」等类型,json.dumps 遇到它们会报错,需要先转换(如日期转字符串)。

5. pickle 简述

pickle 能把任意 Python 对象序列化成字节流(JSON 只能存基本类型):

python 复制代码
import pickle

config = {"theme": "dark", "sizes": (16, 24), "enabled": True}

# 序列化到文件
with open("config.pkl", "wb") as f:   # 二进制模式
    pickle.dump(config, f)

# 反序列化
with open("config.pkl", "rb") as f:
    loaded = pickle.load(f)
print(loaded["sizes"])  # 输出:(16, 24)  ------ 元组被完整保留

🚫 避坑 :pickle 只能用于自己可控的、可信的数据绝不要 pickle.load 来自不可信来源的文件------反序列化可以执行任意代码,是严重的安全风险。跨语言、跨系统交换数据请用 JSON。

6. 实战演练:读取 CSV 汇总成 JSON 报告

需求:读一个订单 CSV 文件,统计总金额、订单数,生成 JSON 报告。

python 复制代码
import csv
import json
from pathlib import Path

def summarize_orders(csv_path: str, report_path: str) -> None:
    """读取订单 CSV,汇总统计并生成 JSON 报告。"""
    orders = []
    with open(csv_path, encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            orders.append(
                {
                    "order_id": row["订单号"],
                    "amount": float(row["金额"]),
                    "status": row["状态"],
                }
            )

    paid_orders = [o for o in orders if o["status"] == "已支付"]
    report = {
        "total_orders": len(orders),
        "paid_orders": len(paid_orders),
        "total_amount": round(sum(o["amount"] for o in orders), 2),
        "paid_amount": round(sum(o["amount"] for o in paid_orders), 2),
    }

    Path(report_path).write_text(
        json.dumps(report, ensure_ascii=False, indent=2),
        encoding="utf-8",
    )
    print(f"报告已生成:{report_path}")


if __name__ == "__main__":
    summarize_orders("orders.csv", "report.json")

假设 orders.csv 内容:

text 复制代码
订单号,金额,状态
A001,199.0,已支付
A002,299.0,待支付
A003,149.0,已支付

生成的 report.json

json 复制代码
{
  "total_orders": 3,
  "paid_orders": 2,
  "total_amount": 647.0,
  "paid_amount": 348.0
}

这个「CSV 进、JSON 出」的流程,正是日常数据处理最常见的样子。

7. 常见错误与避坑

  1. 忘写 encoding="utf-8":中文乱码,Windows 上尤其明显。
  2. "w" 覆盖了原文件 :只想追加却用了 "w",数据被清空。追加要用 "a"
  3. CSV 少了 newline="":Windows 下出现多余空行。
  4. ensure_ascii=True(默认) :中文变 \uXXXX,可读性差,加 ensure_ascii=False
  5. 对不可信文件用 pickle:安全风险,改用 JSON。

8. 小结

  • with open(...) 自动关文件;文本读写加 encoding="utf-8",二进制用 rb/wb
  • pathlib/ 拼路径、read_text/write_text 读写、glob 匹配,现代首选。
  • csv.DictReader 把每行变字典,最易读。
  • json.dumps/loads/dump/load 四个函数,ensure_ascii=False 保中文,indent 美化。
  • pickle 能存任意对象但只用于可信数据;跨语言交换用 JSON。

9. 练习与思考

  1. 写一个脚本,读取用户输入的文本,追加写入 diary.txt(用 "a" 模式)。
  2. 把一份学生成绩的字典列表 [{"name": "张三", "score": 90}, ...] 写成 CSV 文件。
  3. pathlib 列出当前目录下所有 .py 文件,并打印它们的名字。
  4. 思考:什么场景该用 JSON、什么场景该用 CSV、什么场景该用 pickle?

💡 提示:第 4 题从「是否结构化」「是否需要跨语言」「是否需要存对象」三个角度思考。

10. 延伸阅读


📚 本系列导航

如果觉得有用,欢迎收藏、点赞、转发,让更多人少走弯路。

相关推荐
小静AI工程实验室1 小时前
Python 爬虫中文乱码排查:严格解码、UTF-8 BOM 与 JSON 转义的 12 项实验
字符编码·爬虫·python
天天被压力1 小时前
【跨市场数据实战 #08】可转债折价机会怎么筛:3个接口抓比价、列表和实时盘口
java·人工智能·python
weixin199701080161 小时前
[特殊字符]️《从0到1搭多平台二手ERP中台:闲鱼+淘宝+京东+拼多多+Mercari统一调度》(附Python源码)
python
王国强20091 小时前
uv 深入指南:重新理解 Python 的包管理、依赖解析与项目工程化
python
巡山小钻风来也1 小时前
【保姆级教程】自定义数据集微调PP-OCRv6文本检测模型
python·ocr·paddlepaddle
baopixiaoz1 小时前
BeeQuant × BeeAgent:用AI加速策略验证
大数据·人工智能·python·区块链
浩瀚地学2 小时前
deepagents学习打卡day04
python·agent
安易算力2 小时前
PUE优化工程实践:从1.5到1.2的制冷架构与气流组织改造路径
网络·python·容器·架构·kubernetes
troy1283 小时前
Codex 安全盲区:代码漏洞生成实测
windows·python·ci/cd·pycharm·django·github·fastapi