外观
03. 文件系统与数据读写(pathlib / JSON / CSV)
本章目标:用 Python 在 Windows 上稳定地“批量处理文件”和“读写结构化数据”。
原理补充:在自动化里,稳定性比“写得快”更重要。用
pathlib.Path可以避免 Windows 路径分隔符、相对路径、编码等细节导致的隐性 bug。
1) pathlib 三件套(最常用)
- 定位路径:
Path("...")/Path.cwd() - 遍历文件:
glob/rglob - 读写文本:
read_text/write_text
python
from pathlib import Path
root = Path("docs") / "src"
md_files = list(root.rglob("*.md"))
print("markdown files:", len(md_files))原理补充:
rglob("*.md")会递归遍历目录;它返回的是Path对象,不是字符串。
2) 读写文本(编码与换行)
读取:
python
from pathlib import Path
p = Path("README.md")
text = p.read_text(encoding="utf-8")
print(text[:200])写入:
python
from pathlib import Path
out = Path("out.txt")
out.write_text("hello\n", encoding="utf-8")原理补充:Windows 上会遇到 UTF-8/BOM、换行(CRLF)等问题。你做“批量替换/生成文件”时,永远显式写
encoding="utf-8"。
3) JSON(写自动化报告必备)
python
import json
from pathlib import Path
data = {
"name": "vitepress-doc",
"count": 3,
"items": ["a", "b", "c"],
}
Path("report.json").write_text(
json.dumps(data, ensure_ascii=False, indent=2),
encoding="utf-8",
)读取 JSON:
python
import json
from pathlib import Path
obj = json.loads(Path("report.json").read_text(encoding="utf-8"))
print(obj["name"])4) CSV(入门版:DictReader / DictWriter)
python
import csv
from pathlib import Path
rows = [
{"file": "a.md", "lines": 10},
{"file": "b.md", "lines": 20},
]
with Path("report.csv").open("w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["file", "lines"])
writer.writeheader()
writer.writerows(rows)原理补充:写 CSV 时带上
newline=""可以避免 Windows 写出空行问题。
练习:为本仓库生成 Markdown 统计报表
目标:扫描 docs/src 下所有 .md 文件,输出 md-report.json。
示例脚本(可直接放到 scripts/md_report.py 运行):
python
import json
from collections import defaultdict
from pathlib import Path
def count_lines(path: Path) -> int:
return len(path.read_text(encoding="utf-8").splitlines())
def main() -> None:
root = Path("docs") / "src"
files = sorted(root.rglob("*.md"))
by_dir = defaultdict(int)
total_lines = 0
items = []
for p in files:
rel = p.relative_to(root).as_posix()
lines = count_lines(p)
total_lines += lines
by_dir[str(p.parent.relative_to(root)).replace("\\\\", "/")] += 1
items.append({"path": rel, "lines": lines})
report = {
"root": root.as_posix(),
"file_count": len(files),
"total_lines": total_lines,
"dirs": dict(sorted(by_dir.items(), key=lambda x: x[0])),
"items": items,
}
Path("md-report.json").write_text(
json.dumps(report, ensure_ascii=False, indent=2),
encoding="utf-8",
)
if __name__ == "__main__":
main()小项目(为后面铺垫)
- 扫描
docs/src/public/:列出所有资源文件 - 扫描
docs/src/**/*.md:查找/<asset>引用 - 输出一份“可能未引用资源”的列表
这会在第 12 章做成一个 CLI 子命令。
1) 用 pathlib 代替 os.path
常用对象:Path。
python
from pathlib import Path
root = Path("docs") / "src"
for p in root.rglob("*.md"):
print(p)2) 读取与写入文本(编码)
python
from pathlib import Path
text = Path("a.txt").read_text(encoding="utf-8")
Path("b.txt").write_text(text, encoding="utf-8")3) JSON
python
import json
from pathlib import Path
data = {"a": 1}
Path("out.json").write_text(json.dumps(data, ensure_ascii=False, indent=2), encoding="utf-8")4) CSV(入门)
- 读写用
csv标准库即可
练习
- 扫描
docs/src下所有 Markdown 文件:统计文件数、总行数、每个目录的文件数 - 输出到
report.json
小项目(为后面铺垫)
- 写一个脚本:找出
docs/src/public下“可能未被引用”的图片(先只做文件列表 + 手动检查)
