跳转到内容

2.3.1 项目:命令行任务管理器

命令行任务管理器架构图

这是 Python 基础阶段的第一个完整小项目。你会把数据结构、函数、文件读写和异常处理组合起来,做出一个真正能保存任务、查看任务、修改任务状态的命令行工具。

  • 综合运用 Python 基础知识(数据结构、函数、文件操作、异常处理)
  • 体验完整的项目开发流程:需求分析 → 设计 → 编码 → 测试
  • 构建一个真正可用的命令行工具

我们要构建一个命令行任务管理器(类似简易版的 Todoist),支持:

  • 添加任务
  • 查看所有任务
  • 标记任务完成
  • 删除任务
  • 数据持久化(关闭程序后数据不丢失)

最终效果:

区域CLI 展示什么
菜单查看、添加、完成、删除或退出
用户操作选择 1 查看所有任务
任务列表三个任务,其中一个已完成
摘要共 3 个任务,已完成 1 个

每个任务需要哪些信息?

task = {
"id": 1,
"title": "学习 Python 基础",
"done": False,
"created_at": "2026-02-09 14:30:00"
}

所有任务存在一个列表中,并保存到 JSON 文件。

模块功能
数据管理加载/保存任务到文件
任务操作增删改查
用户界面菜单显示、输入处理

先实现一个最简单的版本,不带文件保存:

# todo.py —— 命令行任务管理器
from datetime import datetime
def show_menu():
"""显示菜单"""
print("\n===== 任务管理器 =====")
print("1. 查看所有任务")
print("2. 添加任务")
print("3. 完成任务")
print("4. 删除任务")
print("5. 退出")
print()
def show_tasks(tasks: list[dict]) -> None:
"""显示所有任务"""
if not tasks:
print("📭 暂无任务,快去添加一个吧!")
return
print("\n📋 任务列表:")
for i, task in enumerate(tasks, 1):
status = "" if task["done"] else " "
print(f' {i}. [{status}] {task["title"]} '
f'(创建于: {task["created_at"][:10]})')
done_count = sum(1 for t in tasks if t["done"])
print(f"\n{len(tasks)} 个任务,已完成 {done_count} 个")
def add_task(tasks: list[dict]) -> None:
"""添加新任务"""
title = input("请输入任务标题: ").strip()
if not title:
print("❌ 任务标题不能为空!")
return
task = {
"id": len(tasks) + 1,
"title": title,
"done": False,
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
tasks.append(task)
print(f"✅ 任务「{title}」已添加!")
def complete_task(tasks: list[dict]) -> None:
"""标记任务为完成"""
show_tasks(tasks)
if not tasks:
return
try:
num = int(input("请输入要完成的任务编号: "))
if 1 <= num <= len(tasks):
task = tasks[num - 1]
if task["done"]:
print(f"⚠️ 任务「{task['title']}」已经完成过了")
else:
task["done"] = True
print(f"✅ 任务「{task['title']}」已标记为完成!")
else:
print("❌ 无效的任务编号!")
except ValueError:
print("❌ 请输入数字!")
def delete_task(tasks: list[dict]) -> None:
"""删除任务"""
show_tasks(tasks)
if not tasks:
return
try:
num = int(input("请输入要删除的任务编号: "))
if 1 <= num <= len(tasks):
removed = tasks.pop(num - 1)
print(f"🗑️ 任务「{removed['title']}」已删除!")
else:
print("❌ 无效的任务编号!")
except ValueError:
print("❌ 请输入数字!")
def main():
"""主函数"""
tasks = []
print("欢迎使用任务管理器!")
while True:
show_menu()
choice = input("请选择操作 (1-5): ").strip()
if choice == "1":
show_tasks(tasks)
elif choice == "2":
add_task(tasks)
elif choice == "3":
complete_task(tasks)
elif choice == "4":
delete_task(tasks)
elif choice == "5":
print("👋 再见!")
break
else:
print("❌ 无效的选择,请输入 1-5")
if __name__ == "__main__":
main()

试一试: 把上面的代码保存为 todo.py,运行 python todo.py


现在程序一关数据就没了。让我们加上文件保存功能:

import json
from pathlib import Path
DATA_FILE = Path("tasks.json")
def load_tasks() -> list[dict]:
"""从文件加载任务"""
if DATA_FILE.exists():
try:
with open(DATA_FILE, "r", encoding="utf-8") as f:
tasks = json.load(f)
print(f"📂 已加载 {len(tasks)} 个任务")
return tasks
except (json.JSONDecodeError, IOError) as e:
print(f"⚠️ 加载数据失败: {e},将使用空列表")
return []
def save_tasks(tasks: list[dict]) -> None:
"""保存任务到文件"""
try:
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(tasks, f, ensure_ascii=False, indent=2)
except IOError as e:
print(f"⚠️ 保存数据失败: {e}")

然后修改 main() 函数:

def main():
tasks = load_tasks() # 启动时加载
print("欢迎使用任务管理器!")
while True:
show_menu()
choice = input("请选择操作 (1-5): ").strip()
if choice == "1":
show_tasks(tasks)
elif choice == "2":
add_task(tasks)
save_tasks(tasks) # 添加后保存
elif choice == "3":
complete_task(tasks)
save_tasks(tasks) # 修改后保存
elif choice == "4":
delete_task(tasks)
save_tasks(tasks) # 删除后保存
elif choice == "5":
save_tasks(tasks) # 退出前保存
print("👋 再见!")
break
else:
print("❌ 无效的选择,请输入 1-5")

基础版完成后,试着添加以下功能来提升自己:

给任务添加优先级(高/中/低),并支持按优先级排序显示。

支持按关键词搜索任务标题。

显示统计信息:总任务数、完成率、今日新增等。

把整个项目用面向对象的方式重构:

class Task:
"""单个任务"""
def __init__(self, title: str, priority: str = ""):
self.title = title
self.priority = priority
self.done = False
self.created_at = datetime.now()
class TaskManager:
"""任务管理器"""
def __init__(self, filename: str = "tasks.json"):
self.filename = filename
self.tasks: list[Task] = []
self.load()
def add(self, title: str, priority: str = "") -> None:
self.tasks.append(Task(title, priority))
def complete(self, index: int) -> None:
self.tasks[index].done = True
def delete(self, index: int) -> None:
self.tasks.pop(index)
def search(self, keyword: str) -> list[Task]:
return [task for task in self.tasks if keyword.lower() in task.title.lower()]
def save(self) -> None:
import json
from pathlib import Path
Path(self.filename).write_text(
json.dumps([task.__dict__ for task in self.tasks], ensure_ascii=False, indent=2),
encoding="utf-8",
)
def load(self) -> None:
import json
from pathlib import Path
path = Path(self.filename)
if not path.exists():
return
data = json.loads(path.read_text(encoding="utf-8"))
self.tasks = []
for item in data:
task = Task(item["title"], item.get("priority", ""))
task.done = item.get("done", False)
self.tasks.append(task)
项目交付参考与讲解
  1. 增加 priority 字段,例如 highmediumlow,然后在展示前按优先级排序。如果优先级相同,就让较早的 created_at 排在前面。
  2. 增加一个 search(keyword) 辅助函数,对标题、状态文本和优先级做不区分大小写的匹配。
  3. 输出总任务数、已完成任务数、待办任务数,以及各优先级的数量。这样每次改完都能快速检查输出是否正确。
  4. 重构成 Task 模型 + TaskManager 类。让类负责 loadsaveaddcompletedeletesearch,CLI 只负责输入和打印。
  5. 自查时,重启程序,确认已保存的任务仍然存在,搜索能返回正确子集,完成或删除任务后,界面和 tasks.json 都同步更新。

完成项目后,对照检查:

  • 程序能正常运行,不会因为非法输入而崩溃
  • 数据保存到文件,重启后数据还在
  • 代码有函数分层,不是一大坨
  • 有适当的错误处理(try/except)
  • 函数有文档字符串
  • 变量命名清晰(符合 PEP 8)
  • 用 Git 管理了项目代码
版本目标交付重点
基础版跑通最小闭环能输入、能处理、能输出,并保留一组示例
标准版形成可展示项目增加配置、日志、错误处理、README 和截图
挑战版接近作品集质量增加评估、对比实验、失败样本分析和下一步路线

建议先完成基础版,不要一开始就追求大而全。每提升一个版本,都要把“新增了什么能力、怎么验证、还有什么问题”写进 README。

学完这一页,至少保留这张证据卡:

项目目标
CLI、爬虫、API、AI API 调用,或集成式 Python 工作坊目标
运行命令
启动项目时使用的准确命令
工件
输出文件、API 响应、JSON 记录、截图或 README 说明
失败检查
依赖、网络、解析、路由、输入验证或 API key 问题
期望产出
可复现的迷你项目文件夹,包含运行结果和一个失败案例