
本文介绍如何使用python的csv模块正确读取分号分隔的tasks.txt文件,结构化提取任务数据,并基于该数据准确计算任务与用户维度的统计指标,最终生成task_overview.txt和user_overview.txt两个报告文件。
本文介绍如何使用python的csv模块正确读取分号分隔的tasks.txt文件,结构化提取任务数据,并基于该数据准确计算任务与用户维度的统计指标,最终生成task_overview.txt和user_overview.txt两个报告文件。
在开发任务管理系统(如课程项目中的task_manager.py)时,常需从结构化文本文件(如tasks.txt)中批量读取、解析并统计任务数据。原始代码存在多个典型问题:文件句柄重复遍历(enumerate(task)后又调用task.readlines())、未重置文件指针导致后续读取为空、列表索引误用(如reports[-1]试图判断完成状态)、日期字符串直接比较(不安全且易出错)等。这些问题导致统计逻辑失效,字典值无法更新。
推荐采用标准库 csv.DictReader 进行健壮解析——它自动将首行作为字段名,每行转为字典,天然支持分号分隔符,大幅提升可读性与可靠性。
✅ 正确实现步骤
1. 结构化加载数据:按用户组织任务
import csv
from datetime import datetime
def load_tasks(filename: str) -> dict:
"""将tasks.txt按用户分组,返回 {username: [task_dict, ...]}"""
users = {}
with open(filename, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f, delimiter=';')
for row in reader:
username = row.pop('user').strip()
if username not in users:
users[username] = []
users[username].append(row)
return users
2. 计算任务总览(task_overview)
关键逻辑:
使用 qbo-mileage CLI 及用户凭证,从 Airtable、Outlook 或 Google Calendar 记录生成 QuickBooks Online 里程 CSV 文件。
- 遍历所有任务,累加总数、已完成/未完成数;
- 对未完成任务,将due date字符串转为datetime对象再与当前日期比较;
- 百分比计算需避免除零(建议添加if result['Tasks'] > 0保护)。
def generate_task_overview(users: dict) -> dict:
stats = {
"Tasks": 0,
"Completed": 0,
"Uncompleted": 0,
"Overdue": 0,
"Percentage Incomplete": 0.0,
"Percentage Overdue": 0.0
}
today = datetime.now()
for task_list in users.values():
for task in task_list:
stats["Tasks"] += 1
if task['completed'].strip() == 'Yes':
stats["Completed"] += 1
else:
stats["Uncompleted"] += 1
try:
due_date = datetime.strptime(task['due date'].strip(), '%Y-%m-%d')
if due_date 0:
stats["Percentage Incomplete"] = (stats["Uncompleted"] / stats["Tasks"]) * 100
stats["Percentage Overdue"] = (stats["Overdue"] / stats["Tasks"]) * 100
return stats
3. 计算用户总览(user_overview)
统计用户总数、每人任务数、总任务数等。注意原需求中 "Name": 0 含义模糊,此处统一替换为 "User_Count" 和各用户明细(可选扩展):
def generate_user_overview(users: dict) -> dict:
user_count = len(users)
total_tasks = sum(len(tasks) for tasks in users.values())
return {
"Users": user_count,
"Total_Tasks": total_tasks,
"Per_User_Tasks": {user: len(tasks) for user, tasks in users.items()}
}
4. 主流程与文件写入
整合逻辑,并写入报告文件:
if __name__ == "__main__":
# 加载数据
users = load_tasks("tasks.txt")
# 生成统计
task_stats = generate_task_overview(users)
user_stats = generate_user_overview(users)
# 写入 task_overview.txt
with open("task_overview.txt", "w", encoding='utf-8') as f:
for k, v in task_stats.items():
f.write(f"{k}: {v}\n")
# 写入 user_overview.txt
with open("user_overview.txt", "w", encoding='utf-8') as f:
for k, v in user_stats.items():
if isinstance(v, dict):
f.write(f"{k}:\n")
for sub_k, sub_v in v.items():
f.write(f" {sub_k}: {sub_v}\n")
else:
f.write(f"{k}: {v}\n")
print("✅ Reports generated: task_overview.txt & user_overview.txt")
⚠️ 注意事项
- 编码安全:始终指定 encoding='utf-8' 防止中文或特殊字符报错;
- 异常处理:对日期解析、空字段等添加try/except,避免程序中断;
- 文件指针:切勿对同一文件对象多次迭代(如先for line in f再f.readlines()),应重开文件或使用f.seek(0);
- 字段校验:生产环境建议检查tasks.txt是否缺失必要列(如user, completed, due date);
- 性能提示:对于超大文件,可考虑流式处理或Pandas;但本场景下csv.DictReader已足够高效。
通过以上结构化设计,代码逻辑清晰、易于维护,并能准确支撑后续报告生成功能。










