

🛠️ 说明 :经过前十九篇的学习,你已掌握 Python 核心语法、文件操作、异常处理、OOP、模块组织和虚拟环境等关键技能。本篇将整合所有知识,带你从零开始开发一个功能完整、结构清晰、可维护的命令行 To-Do List(待办事项)应用。
你将实践:
- 项目目录结构设计
- 面向对象建模(
Task、TaskManager) - JSON 数据持久化
- 命令行交互(
argparse+ 用户输入) - 异常处理与用户友好提示
- 虚拟环境与依赖管理
1. 项目目标与功能清单
✅ 最终应用支持以下操作:
bash
# 添加任务
python todo.py add "买牛奶"
# 列出所有任务
python todo.py list
# 标记任务完成
python todo.py done 1
# 删除任务
python todo.py remove 2
# 显示帮助
python todo.py --help
数据存储格式(tasks.json):
json
[
{
"id": 1,
"title": "买牛奶",
"completed": false,
"created_at": "2025-12-18T16:30:00"
}
]
2. 项目结构设计
遵循前文最佳实践:
todo-cli/
├── venv/ ← 虚拟环境(不提交)
├── requirements.txt
├── .gitignore
├── README.md
├── todo.py ← 主程序入口
└── todolib/ ← 核心功能包
├── __init__.py
├── task.py ← Task 类
├── storage.py ← 文件读写
└── manager.py ← 任务管理逻辑
3. 步骤一:创建虚拟环境与依赖
bash
mkdir todo-cli && cd todo-cli
python -m venv venv
source venv/bin/activate # Linux/Mac
# venv\Scripts\activate # Windows
# 目前无第三方依赖,但保留文件
echo "# 项目依赖" > requirements.txt
💡 本项目仅使用标准库,无需安装额外包!
4. 步骤二:定义 Task 类(todolib/task.py)
python
from datetime import datetime
from typing import Dict
class Task:
def __init__(self, title: str, completed: bool = False, created_at: str = None):
self.title = title
self.completed = completed
self.created_at = created_at or datetime.now().isoformat()
self.id = None # 将由 TaskManager 分配
def to_dict(self) -> Dict:
return {
"id": self.id,
"title": self.title,
"completed": self.completed,
"created_at": self.created_at
}
@classmethod
def from_dict(cls, data: Dict) -> "Task":
task = cls(data["title"], data["completed"], data["created_at"])
task.id = data["id"]
return task
def __str__(self):
status = "✓" if self.completed else "○"
return f"[{status}] {self.title}"
✅ 使用类型提示(
typing)提升可读性✅ 支持序列化(
to_dict)与反序列化(from_dict)
5. 步骤三:实现数据存储(todolib/storage.py)
python
import json
from pathlib import Path
from typing import List, Dict
from .task import Task
TASKS_FILE = Path("tasks.json")
def load_tasks() -> List[Task]:
if not TASKS_FILE.exists():
return []
try:
data = json.loads(TASKS_FILE.read_text(encoding="utf-8"))
return [Task.from_dict(item) for item in data]
except (json.JSONDecodeError, KeyError) as e:
print(f"⚠️ 警告:任务文件损坏,已重置。错误: {e}")
return []
def save_tasks(tasks: List[Task]) -> None:
data = [task.to_dict() for task in tasks]
TASKS_FILE.write_text(
json.dumps(data, ensure_ascii=False, indent=2),
encoding="utf-8"
)
🔒 安全读取:捕获 JSON 解析错误,防止程序崩溃
6. 步骤四:任务管理逻辑(todolib/manager.py)
python
from typing import List
from .task import Task
from .storage import load_tasks, save_tasks
class TaskManager:
def __init__(self):
self.tasks: List[Task] = load_tasks()
self._next_id = max((t.id for t in self.tasks), default=0) + 1
def add_task(self, title: str) -> Task:
task = Task(title)
task.id = self._next_id
self._next_id += 1
self.tasks.append(task)
save_tasks(self.tasks)
return task
def get_task_by_id(self, task_id: int) -> Task:
for task in self.tasks:
if task.id == task_id:
return task
raise ValueError(f"任务 ID {task_id} 不存在")
def mark_done(self, task_id: int) -> None:
task = self.get_task_by_id(task_id)
task.completed = True
save_tasks(self.tasks)
def remove_task(self, task_id: int) -> None:
task = self.get_task_by_id(task_id)
self.tasks.remove(task)
save_tasks(self.tasks)
def list_tasks(self, show_completed: bool = True) -> List[Task]:
if show_completed:
return self.tasks
return [t for t in self.tasks if not t.completed]
✅ 封装业务逻辑,主程序只需调用方法
✅ 自动分配唯一 ID,避免冲突
7. 步骤五:主程序入口(todo.py)
python
#!/usr/bin/env python3
import argparse
from todolib.manager import TaskManager
def main():
parser = argparse.ArgumentParser(description="简易命令行 To-Do List")
subparsers = parser.add_subparsers(dest="command", help="可用命令")
# add
add_parser = subparsers.add_parser("add", help="添加新任务")
add_parser.add_argument("title", help="任务内容")
# list
list_parser = subparsers.add_parser("list", help="列出任务")
list_parser.add_argument("--all", action="store_true", help="显示已完成任务")
# done
done_parser = subparsers.add_parser("done", help="标记任务完成")
done_parser.add_argument("id", type=int, help="任务ID")
# remove
remove_parser = subparsers.add_parser("remove", help="删除任务")
remove_parser.add_argument("id", type=int, help="任务ID")
args = parser.parse_args()
if not args.command:
parser.print_help()
return
manager = TaskManager()
try:
if args.command == "add":
task = manager.add_task(args.title)
print(f"✅ 已添加任务 #{task.id}: {task.title}")
elif args.command == "list":
tasks = manager.list_tasks(show_completed=args.all)
if not tasks:
print("📭 暂无任务")
return
for task in tasks:
print(f"#{task.id} {task}")
elif args.command == "done":
manager.mark_done(args.id)
print(f"🎉 任务 #{args.id} 已完成!")
elif args.command == "remove":
manager.remove_task(args.id)
print(f"🗑️ 任务 #{args.id} 已删除")
except ValueError as e:
print(f"❌ 错误: {e}")
except Exception as e:
print(f"💥 未知错误: {e}")
if __name__ == "__main__":
main()
✨ 用户友好提示(✅/❌/🎉 等 emoji 提升体验)
🛡️ 异常捕获:防止因无效 ID 导致崩溃
8. 测试你的应用
bash
# 添加任务
python todo.py add "学习 Python"
python todo.py add "写博客"
# 查看任务
python todo.py list
# 输出:
# #1 [○] 学习 Python
# #2 [○] 写博客
# 完成任务
python todo.py done 1
# 再次查看(默认隐藏已完成)
python todo.py list
# 输出:
# #2 [○] 写博客
# 查看所有
python todo.py list --all
# 删除任务
python todo.py remove 2
💾 所有数据自动保存到
tasks.json,重启后依然存在!
9. 项目优化建议(进阶)
- 添加单元测试 (使用
unittest或pytest) - 支持任务优先级或截止日期
- 实现"清空已完成"命令
- 用
rich库美化终端输出(需安装第三方包) - 打包为可执行命令 (如
pip install -e .)
10. 总结:你已掌握的核心能力
| 技能 | 在本项目中的体现 |
|---|---|
| OOP 设计 | Task、TaskManager 封装数据与行为 |
| 文件操作 | storage.py 安全读写 JSON |
| 异常处理 | 捕获无效 ID、文件损坏等错误 |
| 命令行交互 | argparse 构建专业 CLI |
| 模块化 | 功能拆分为 todolib/ 包 |
| 虚拟环境 | 隔离开发环境 |
🎯 恭喜!你已具备独立开发小型 Python 应用的能力。
下一步方向
- 扩展功能:添加子任务、分类标签、搜索
- 学习 Web 开发:用 Flask/Django 将此应用转为网页版
- 探索自动化:用此工具管理你的学习计划
- 阅读开源项目 :如 todo-txt
🐍 编程不是学出来的,是写出来的。
从今天起,你不再只是学习者,而是创造者!
继续编码,用 Python 改变你的世界!

