
python标准库不提供“读一行即删一行”的文件操作函数;为应对程序意外中断,推荐用独立进度文件记录已处理行号,重启时跳过已处理内容,兼顾效率与可靠性。
在实际数据处理任务中(如日志解析、批量API调用或ETL流程),常需逐行读取文本文件并确保每行仅被处理一次。但若程序因崩溃、断电或异常退出而中断,传统 readlines() + 全量重写的方式(如每次删除已读行)不仅I/O开销巨大,还存在数据丢失风险——尤其当写入中途失败时,原文件可能被清空或截断。
更健壮的解决方案是解耦“读取”与“状态记录”:不修改原始文件,而是将处理进度(如最新完成的行号)持久化到独立的小型元数据文件中。这样既保持源文件完整性,又实现故障恢复能力。
✅ 推荐实现:基于行号的进度追踪
以下是一个轻量、线程安全(单进程场景下)、可直接复用的处理函数:
def process_file(filepath, progress_filepath):
# 1. 读取上次中断位置(默认从第0行开始)
try:
with open(progress_filepath, 'r') as pf:
last_processed_line_number = int(pf.read().strip())
except (FileNotFoundError, ValueError):
last_processed_line_number = 0
# 2. 流式读取原始文件(避免一次性加载全部内容到内存)
with open(filepath, 'r', encoding='utf-8') as f:
for line_num, line in enumerate(f, start=1):
if line_num <= last_processed_line_number:
continue # 跳过已处理行
# ? 此处插入你的业务逻辑(如解析、发送请求、写入数据库等)
print(f"Processing line {line_num}: {line.rstrip()}")
# 3. 立即更新进度(关键!确保原子性与及时性)
try:
with open(progress_filepath, 'w') as pf:
pf.write(str(line_num))
except OSError as e:
print(f"Warning: Failed to update progress file: {e}")
# 可选:记录警告但不停止主流程,保证业务连续性⚠️ 使用注意事项
- 编码兼容性:显式指定 encoding='utf-8' 避免中文等非ASCII字符报错;
- 进度文件路径:建议使用绝对路径或与源文件同目录下的 .progress 文件(如 data.txt.progress),便于管理;
- 性能优化:对超大文件(GB级),避免 readlines() 全加载;上述示例采用逐行迭代(for line in f),内存占用恒定;
- 并发安全:本方案不适用于多进程同时处理同一文件;如需并发,请引入文件锁(如 portalocker 库)或改用数据库/消息队列;
- 原子性保障:进度写入虽小,但仍建议在关键任务中添加 os.replace() 或临时文件+重命名来模拟原子写入(进阶需求);
- 清理策略:处理完成后,可选择删除进度文件,或保留用于审计。
? 总结
“边读边删”不是Python文件I/O的设计范式,强行模拟反而降低鲁棒性。真正工业级的做法是:让数据只读、让状态可追溯、让恢复变简单。通过一个轻量进度文件,你既能精准续跑,又能保留原始输入用于验证与回溯——这是比反复重写文件更优雅、更可靠的数据处理哲学。
立即学习“Python免费学习笔记(深入)”;










