文件读写
运维脚本经常读取日志、配置、资产清单,或写入巡检报告、临时状态文件。Python 用 open() 与 pathlib.Path 处理路径,务必使用 with 上下文自动关闭文件句柄。
pathlib:推荐的路径方式
from pathlib import Path
# 项目根下的 data 目录
base = Path.home() / "python-for-ops" / "data"
log_file = base / "app.log"
print(log_file.name) # app.log
print(log_file.suffix) # .log
print(log_file.exists()) # False(示例环境可能不存在)
# 确保目录存在
base.mkdir(parents=True, exist_ok=True)
读取整个文件
from pathlib import Path
path = Path("data/app.log")
# 文本模式,utf-8 编码;文件不存在会 FileNotFoundError
content = path.read_text(encoding="utf-8")
print(len(content))
# 大文件不要 read_text 一次读入,应逐行
逐行读取(日志场景)
from pathlib import Path
path = Path("data/app.log")
error_count = 0
with path.open(encoding="utf-8") as f:
for line_num, line in enumerate(f, start=1):
line = line.strip()
if not line or line.startswith("#"):
continue # 跳过空行与注释
if "ERROR" in line:
error_count += 1
print(f"L{line_num}: {line[:80]}")
print(f"ERROR 行数: {error_count}")
encoding="utf-8" 避免中文日志乱码;Windows 遗留文件可能是 gbk,需按实际情况调整。
写入与追加
from pathlib import Path
from datetime import datetime
report = Path("data/inspection.txt")
# 覆盖写入
report.write_text("巡检开始\n", encoding="utf-8")
# 追加模式
timestamp = datetime.now().isoformat(timespec="seconds")
with report.open("a", encoding="utf-8") as f:
f.write(f"[{timestamp}] web-01 OK\n")
f.write(f"[{timestamp}] db-01 FAIL disk=92%\n")
print(report.read_text(encoding="utf-8"))
| 模式 | 含义 |
|---|---|
"r" | 只读(默认) |
"w" | 覆盖写 |
"a" | 追加 |
"r+" | 读写 |
写入多行列表
from pathlib import Path
hosts = ["web-01", "web-02", "db-01"]
out = Path("data/hosts.txt")
# writelines 不会自动加换行
out.write_text("\n".join(hosts) + "\n", encoding="utf-8")
安全:原子写入与临时文件
避免写到一半被中断导致配置文件损坏:
import tempfile
from pathlib import Path
target = Path("data/state.json")
data = '{"last_run": "2026-07-23", "status": "ok"}'
# 先写临时文件,再替换(同目录保证同一文件系统)
with tempfile.NamedTemporaryFile(
mode="w",
encoding="utf-8",
dir=target.parent,
delete=False,
suffix=".tmp",
) as tmp:
tmp.write(data)
tmp_path = Path(tmp.name)
tmp_path.replace(target) # 原子替换
print("写入完成:", target.read_text(encoding="utf-8"))
实战:过滤日志到单独文件
from pathlib import Path
src = Path("data/access.log")
dst = Path("data/access_5xx.log")
with src.open(encoding="utf-8") as fin, dst.open("w", encoding="utf-8") as fout:
for line in fin:
parts = line.split()
if len(parts) >= 2 and parts[-2].startswith("5"):
fout.write(line)
print(f"已导出 5xx 到 {dst}")
小结
- 路径用
pathlib.Path,少用字符串拼接 - 读大日志用
for line in f,省内存 - 始终指定
encoding="utf-8" - 关键配置用临时文件 +
replace原子写入
下一章学习 JSON,处理 API 响应与结构化配置。