文章

Python 首批细教程 · 02B:把成绩工具升级成 JSON 成绩册

#268 · 2026-05-13 · Python 教程拆解

对应原仓库Day01-15/11.文件和异常.mdDay01-15/07.字符串和常用数据结构.md

已提供可运行示例/tutorial-assets/python-100-days/02b-gradebook-json/(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02b-gradebook-json/

上一节我们把成绩统计做成了 CLI,这一节再往前走一步:把数据保存下来

目标

程序启动时读取 gradebook.json,录入新学生后写回文件。这样你第二次启动程序,之前录的人成绩还在。

Step 1:准备 JSON 文件

示例目录已经提供 gradebook.json(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02b-gradebook-json/gradebook.json):

[
  {"name": "张三", "score": 88},
  {"name": "李四", "score": 92}
]

Step 2:写读写函数

示例目录已经提供 storage.py(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02b-gradebook-json/storage.py):

import json
from pathlib import Path


DATA_FILE = Path("gradebook.json")


def load_records() -> list[dict]:
    if not DATA_FILE.exists():
        return []
    with DATA_FILE.open("r", encoding="utf-8") as file:
        return json.load(file)


def save_records(records: list[dict]) -> None:
    with DATA_FILE.open("w", encoding="utf-8") as file:
        json.dump(records, file, ensure_ascii=False, indent=2)

Step 3:写主程序

示例目录已经提供 main.py(站点源码路径:blog-src/static/tutorial-assets/python-100-days/02b-gradebook-json/main.py):

from storage import load_records, save_records


def main():
    records = load_records()
    print("当前已有记录:", records)

    while True:
        text = input("输入 姓名,分数;输入 q 退出: ").strip()
        if text.lower() == "q":
            break
        try:
            name, score_text = text.split(",")
            score = int(score_text.strip())
            records.append({"name": name.strip(), "score": score})
        except ValueError:
            print("输入格式错误,例如:王五,76")

    save_records(records)
    print("保存完成")


if __name__ == "__main__":
    main()

运行:

cd blog-src/static/tutorial-assets/python-100-days/02b-gradebook-json
python main.py

你会得到什么

这一步其实已经在做一个最小的数据持久化系统了:

  • 用列表组织多条记录;
  • 用字典表示单条记录;
  • 用 JSON 存到磁盘;
  • 用异常处理拦住坏输入。

进阶任务

  1. 增加“按姓名查询成绩”功能。
  2. 增加“删除某个学生”功能。
  3. 写一个“只保留最高 5 分记录”的函数。

常见坑

  • 忘记 ensure_ascii=False,中文会变成 Unicode 转义。
  • 读文件时没判断文件是否存在。
  • 写 JSON 时不加 indent=2,后面很难人工查看。