# Python 项目开发示例:待办事项管理器
下面是一个完整的 Python 项目示例,展示如何开发一个简单的命令行待办事项管理器。这个项目包含了良好的代码结构、异常处理和基本功能。
```python
"""
todo_manager.py
一个简单的命令行待办事项管理器
支持添加、查看、完成和删除任务
"""
import json
import os
from datetime import datetime
from typing import List, Dict, Any, Optional
class Task:
"""表示单个任务"""
def __init__(self, title: str, description: str = "", due_date: Optional[str] = None):
self.id = None
self.title = title
self.description = description
self.created_at = datetime.now().isoformat()
self.due_date = due_date
self.completed = False
self.completed_at = None
def to_dict(self) -> Dict[str, Any]:
"""将任务对象转换为字典"""
return {
"id": self.id,
"title": self.title,
"description": self.description,
"created_at": self.created_at,
"due_date": self.due_date,
"completed": self.completed,
"completed_at": self.completed_at
}
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'Task':
"""从字典创建任务对象"""
task = cls(data["title"], data.get("description", ""))
task.id = data["id"]
task.created_at = data["created_at"]
task.due_date = data.get("due_date")
task.completed = data["completed"]
task.completed_at = data.get("completed_at")
return task
def __str__(self) -> str:
status = "✓" if self.completed else "✗"
due_info = f" | 截止: {self.due_date}" if self.due_date else ""
return f"{self.id:3d}. [{status}] {self.title}{due_info}"
class TodoManager:
"""待办事项管理器"""
def __init__(self, filename: str = "tasks.json"):
self.filename = filename
self.tasks: List[Task] = []
self.next_id = 1
self.load_tasks()
def load_tasks(self) -> None:
"""从文件加载任务"""
if os.path.exists(self.filename):
try:
with open(self.filename, 'r', encoding='utf-8') as f:
data = json.load(f)
for task_data in data:
task = Task.from_dict(task_data)
self.tasks.append(task)
if task.id and task.id >= self.next_id:
self.next_id = task.id + 1
except (json.JSONDecodeError, IOError) as e:
print(f"加载任务时出错: {e}")
self.tasks = []
def save_tasks(self) -> None:
"""保存任务到文件"""
try:
data = [task.to_dict() for task in self.tasks]
with open(self.filename, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
except IOError as e:
print(f"保存任务时出错: {e}")
def add_task(self, title: str, description: str = "", due_date: Optional[str] = None) -> Task:
"""添加新任务"""
task = Task(title, description, due_date)
task.id = self.next_id
self.next_id += 1
self.tasks.append(task)
self.save_tasks()
return task
def get_task(self, task_id: int) -> Optional[Task]:
"""根据ID获取任务"""
for task in self.tasks:
if task.id == task_id:
return task
return None
def list_tasks(self, show_completed: bool = True, filter_keyword: Optional[str] = None) -> List[Task]:
"""列出任务,可筛选"""
filtered_tasks = []
for task in self.tasks:
# 根据完成状态筛选
if not show_completed and task.completed:
continue
# 根据关键字筛选
if filter_keyword:
keyword_lower = filter_keyword.lower()
if (keyword_lower not in task.title.lower() and
keyword_lower not in task.description.lower()):
continue
filtered_tasks.append(task)
return filtered_tasks
def complete_task(self, task_id: int) -> bool:
"""标记任务为完成"""
task = self.get_task(task_id)
if task and not task.completed:
task.completed = True
task.completed_at = datetime.now().isoformat()
self.save_tasks()
return True
return False
def delete_task(self, task_id: int) -> bool:
"""删除任务"""
task = self.get_task(task_id)
if task:
self.tasks.remove(task)
self.save_tasks()
return True
return False
def get_stats(self) -> Dict[str, Any]:
"""获取统计信息"""
total = len(self.tasks)
completed = sum(1 for task in self.tasks if task.completed)
pending = total - completed
return {
"total": total,
"completed": completed,
"pending": pending,
"completion_rate": completed / total * 100 if total > 0 else 0
}
def display_menu() -> None:
"""显示菜单"""
print("\n" + "="*50)
print("待办事项管理器")
print("="*50)
print("1. 添加任务")
print("2. 查看所有任务")
print("3. 查看待办任务")
print("4. 标记任务为完成")
print("5. 删除任务")
print("6. 搜索任务")
print("7. 统计信息")
print("8. 退出")
print("="*50)
def get_input(prompt: str, required: bool = True) -> str:
"""获取用户输入"""
while True:
value = input(prompt).strip()
if not value and required:
print("此项为必填项,请输入内容。")
else:
return value
def main():
"""主程序"""
manager = TodoManager()
while True:
display_menu()
try:
choice = get_input("请选择操作 (1-8): ")
if choice == "1": # 添加任务
print("\n--- 添加新任务 ---")
title = get_input("任务标题: ")
description = get_input("任务描述 (可选): ", required=False)
due_date = get_input("截止日期 (YYYY-MM-DD, 可选): ", required=False)
if due_date:
# 简单验证日期格式
try:
datetime.strptime(due_date, "%Y-%m-%d")
except ValueError:
print("日期格式无效,使用默认值。")
due_date = None
task = manager.add_task(title, description, due_date)
print(f"任务 '{task.title}' 已添加 (ID: {task.id})")
elif choice == "2": # 查看所有任务
print("\n--- 所有任务 ---")
tasks = manager.list_tasks(show_completed=True)
if not tasks:
print("暂无任务。")
else:
for task in tasks:
print(task)
if task.description:
print(f" 描述: {task.description}")
if task.completed and task.completed_at:
completed_date = datetime.fromisoformat(task.completed_at).strftime("%Y-%m-%d")
print(f" 完成于: {completed_date}")
print()
elif choice == "3": # 查看待办任务
print("\n--- 待办任务 ---")
tasks = manager.list_tasks(show_completed=False)
if not tasks:
print("暂无待办任务。")
else:
for task in tasks:
print(task)
if task.description:
print(f" 描述: {task.description}")
if task.due_date:
print(f" 截止日期: {task.due_date}")
print()
elif choice == "4": # 标记任务为完成
print("\n--- 标记任务为完成 ---")
task_id_str = get_input("请输入任务ID: ")
try:
task_id = int(task_id_str)
if manager.complete_task(task_id):
print(f"任务 {task_id} 已标记为完成。")
else:
print(f"未找到任务 {task_id} 或任务已完成。")
except ValueError:
print("请输入有效的任务ID(数字)。")
elif choice == "5": # 删除任务
print("\n--- 删除任务 ---")
task_id_str = get_input("请输入要删除的任务ID: ")
try:
task_id = int(task_id_str)
if manager.delete_task(task_id):
print(f"任务 {task_id} 已删除。")
else:
print(f"未找到任务 {task_id}。")
except ValueError:
print("请输入有效的任务ID(数字)。")
elif choice == "6": # 搜索任务
print("\n--- 搜索任务 ---")
keyword = get_input("搜索关键词: ")
tasks = manager.list_tasks(show_completed=True, filter_keyword=keyword)
if not tasks:
print(f"未找到包含 '{keyword}' 的任务。")
else:
print(f"找到 {len(tasks)} 个相关任务:")
for task in tasks:
print(task)
if task.description:
print(f" 描述: {task.description}")
print()
elif choice == "7": # 统计信息
print("\n--- 统计信息 ---")
stats = manager.get_stats()
print(f"总任务数: {stats['total']}")
print(f"已完成: {stats['completed']}")
print(f"待完成: {stats['pending']}")
print(f"完成率: {stats['completion_rate']:.1f}%")
elif choice == "8": # 退出
print("感谢使用待办事项管理器,再见!")
break
else:
print("无效选择,请选择 1-8 之间的数字。")
except KeyboardInterrupt:
print("\n\n程序被中断,正在退出...")
break
except Exception as e:
print(f"发生错误: {e}")
if __name__ == "__main__":
main()
```
## 项目结构说明
这个待办事项管理器项目展示了以下Python开发最佳实践:
### 1. **代码组织**
- 使用面向对象编程(OOP)设计
- 清晰的类结构:`Task` 和 `TodoManager`
- 将功能模块化,每个方法负责单一功能
### 2. **功能特性**
- 添加、查看、完成和删除任务
- 任务持久化存储(JSON文件)
- 任务搜索和筛选
- 统计信息展示
### 3. **代码质量**
- 类型提示(Type Hints)
- 全面的错误处理
- 清晰的文档字符串
- 用户友好的交互界面
### 4. **运行项目**
1. 将代码保存为 `todo_manager.py`
2. 在终端运行:`python todo_manager.py`
3. 按照菜单提示操作
### 5. **扩展建议**
可以在此基础上添加以下功能:
- 任务分类/标签系统
- 任务优先级设置
- 截止日期提醒
- 图形用户界面(GUI)
- 数据导出功能
- 云同步功能
这个项目展示了Python开发的典型模式,包括文件操作、数据序列化、用户交互和错误处理等核心概念。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。