1. 为什么选择命令行待办事项应用
在图形界面大行其道的今天,命令行工具依然保持着独特的生命力。我最初接触命令行待办事项是在2015年处理服务器维护任务时,当时需要快速记录几十台服务器的维护状态。图形界面工具在SSH连接中显得笨拙,而一个简单的命令行工具让我在终端里就完成了所有记录。
命令行待办事项的核心优势在于:
- 极简高效:无需启动臃肿的GUI程序,一个命令就能完成增删改查
- 脚本集成:可以轻松嵌入自动化流程,比如我常用它来跟踪CI/CD管道的执行状态
- 跨平台一致:无论是在Windows的PowerShell、macOS的Terminal还是Linux的Bash中,操作体验完全一致
- 资源占用低:我的老款笔记本跑图形界面卡顿时,命令行工具依然流畅运行
提示:如果你经常需要在不同设备间切换工作环境,命令行工具通过简单的配置文件同步就能实现全平台数据一致,这是很多图形应用难以做到的。
2. 基础架构设计与技术选型
2.1 存储方案对比
我测试过三种主流存储方案:
- 纯文本文件:最简单但缺乏结构化查询能力
- SQLite数据库:轻量且支持复杂查询(最终选择)
- JSON文件:结构化但写入性能较差
# SQLite表结构示例 CREATE TABLE todos ( id INTEGER PRIMARY KEY, task TEXT NOT NULL, status INTEGER DEFAULT 0, # 0=待办 1=完成 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, priority INTEGER DEFAULT 1 # 1-3优先级 );2.2 命令行交互方案
考虑过argparse和click两个库:
- argparse:Python标准库,功能基础
- click:第三方库,支持彩色输出和复杂参数(最终选择)
# 最终实现的命令示例 todo add "完成项目文档" --priority 2 todo list --status active todo complete 3 # 完成ID为3的任务3. 核心功能实现细节
3.1 任务添加的防呆设计
实际使用中发现几个常见问题:
- 重复添加相同任务
- 优先级数值超出范围
- 任务描述包含特殊字符
解决方案代码片段:
def validate_task(description): if not description.strip(): raise ClickException("任务描述不能为空") if len(description) > 255: raise ClickException("描述过长(最大255字符)") if any(char in description for char in ['"', "'", "\\"]): raise ClickException("描述包含非法字符") def validate_priority(priority): try: priority = int(priority) if not 1 <= priority <= 3: raise ValueError return priority except ValueError: raise ClickException("优先级必须是1-3的整数")3.2 列表展示的视觉优化
通过颜色区分不同状态的任务:
- 黄色:高优先级(priority=3)
- 绿色:已完成
- 红色:过期任务(创建超过7天未完成)
def colorize_task(task): if task['status'] == 1: return click.style(task['description'], fg='green') elif task['priority'] == 3: return click.style(task['description'], fg='yellow') elif (datetime.now() - task['created_at']).days > 7: return click.style(task['description'], fg='red') return task['description']4. 高级功能实现
4.1 数据统计与报表
添加了每周自动统计功能:
def generate_report(): conn = sqlite3.connect(DB_FILE) cursor = conn.cursor() # 本周完成数 cursor.execute(""" SELECT COUNT(*) FROM todos WHERE status = 1 AND created_at > date('now', '-7 days') """) completed = cursor.fetchone()[0] # 优先级分布 cursor.execute(""" SELECT priority, COUNT(*) FROM todos WHERE status = 0 GROUP BY priority """) priorities = dict(cursor.fetchall()) return { 'completed': completed, 'pending_by_priority': priorities }4.2 与系统集成
Linux/macOS:添加bash自动补全
# ~/.bashrc 添加 complete -F _todo_completion todo _todo_completion() { local cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $(compgen -W "add list complete delete report" -- $cur) ) }Windows:创建快捷命令
# 在profile.ps1中添加 function td { python /path/to/todo.py $args }5. 实际使用中的经验教训
- 时区问题:数据库中的时间戳最好统一存储为UTC,显示时再转换
- 并发写入:需要处理多个终端同时修改时的锁问题
- 备份策略:我设置了一个cronjob每天自动备份SQLite文件
# 处理并发写入的代码片段 def safe_db_write(func): def wrapper(*args, **kwargs): max_retries = 3 for attempt in range(max_retries): try: return func(*args, **kwargs) except sqlite3.OperationalError as e: if "database is locked" in str(e) and attempt < max_retries - 1: time.sleep(0.1 * (attempt + 1)) continue raise return wrapper6. 性能优化技巧
- 索引优化:为常用查询字段添加索引
CREATE INDEX idx_status ON todos(status); CREATE INDEX idx_priority ON todos(priority);- 批量操作:处理大量任务时使用事务
with sqlite3.connect(DB_FILE) as conn: cursor = conn.cursor() cursor.executemany( "INSERT INTO todos(task) VALUES (?)", [("任务1",), ("任务2",), ("任务3",)] )- 延迟加载:列表分页显示
def list_tasks(limit=10, offset=0): cursor.execute( "SELECT * FROM todos ORDER BY created_at DESC LIMIT ? OFFSET ?", (limit, offset) ) return cursor.fetchall()7. 扩展思路
- 邮件提醒:对高优先级且超过3天未完成的任务发送提醒
- API接口:用Flask添加RESTful接口实现跨设备同步
- 自然语言识别:解析"明天下午三点前完成报告"这样的时间描述
# 自然语言解析示例(使用dateparser库) import dateparser def parse_due_date(text): date_str = re.search(r'在(.+?)之前', text) if date_str: return dateparser.parse(date_str.group(1)) return None这个命令行待办事项工具已经陪伴我完成了数百个项目任务,它的价值不在于技术复杂度,而在于完美适应了我的工作流。每次打开终端,第一眼就能看到待办事项的状态,这种无缝集成的体验是图形界面应用难以提供的。