☰
Python命令行待办事项管理器:用rich库打造表格版增删改查工具
2026/10/7 15:50:37 网站建设 项目流程

写这个待办事项管理器,起因其实特别朴素:我用过手机备忘录、用过桌面便签、甚至试过纸上打勾,最后所有待办都散落在不同地方,越记越乱。后来想着反正日常离不开 Python,干脆给自己写一个命令行里就能用的待办事项管理器,数据存在本地,表格输出,功能一次做齐——增删改查、优先级、截止日期、完成状态、搜索、统计全都有。这篇文章就把整个项目的设计思路、核心实现和踩坑过程完整拆一遍,适合正在学 Python 想练手的人,也适合想要一个真正能日常使用的效率工具的上班族。

1. 项目整体设计与思路拆解

1.1 “完美功能”到底指什么

我开始动手前先做了一个需求边界梳理,把“待办事项管理器”该有的功能列了个清单,并且明确砍掉了哪些花哨的东西。核心功能定为:添加任务、查看任务列表、标记完成、编辑任务、删除任务、按关键字搜索、按状态/优先级/截止日期过滤、统计完成率。这些是日常管理待办最刚需的能力,任何一个缺失都会让人觉得“不太好用”。

同时我主动放弃了三类功能:第一是复杂的分类标签体系,第二是云同步,第三是桌面弹窗提醒。原因是这些功能会显著增加代码复杂度和依赖,但对一个命令行工具来说,真正高频使用的还是那套增删改查。提醒功能完全可以用系统自带的日历或者手机闹钟代替,没必要在终端里硬造一个半成品。把核心体验做扎实,比堆砌功能列表重要得多。

界面形态选的是“表格版”而不是普通的文本逐行打印,这一点也是有意为之。表格能把任务的状态、优先级、截止日期、标题这些字段对齐展示,扫一眼就能看出今天该做什么、哪件事快逾期了。相比“第1条:xxx,第2条:yyy”这种纯文本输出,表格的信息密度和可读性完全不在一个级别。这也是项目名里特意强调“表格版”的原因。

1.2 为什么用纯 Python 标准库加一个渲染库

技术选型上我做了两个层面的决策:数据存储和表格渲染。数据存储直接用 JSON 文件,没有引入 SQLite 或其它数据库。理由很务实:待办事项的数据量级通常在几十到几百条,JSON 文件读写完全够用,而且文件内容可以用文本编辑器直接打开查看和修改,对用户极其友好。SQLite 固然更“正规”,但在这个场景里属于杀鸡用牛刀,还会让代码里充满 SQL 拼接和游标操作,维护成本不低。

表格渲染选择的是rich库,三行代码就能输出一个对齐美观的终端表格,还自带颜色和边框样式。这里我要说明一个取舍:rich是第三方库,需要pip install rich,但对这个项目来说收益远大于成本。它让“表格版”这个核心卖点得以高质量实现——列宽自动计算、长文本自动换行、优先级字段可以上色标红。如果完全依赖标准库手写对齐逻辑,处理中文宽度和超长文本会非常痛苦,代码量至少翻一倍,效果还不一定好。

主程序结构上,我按“数据层—业务层—展现层”的思路拆成了三个模块:数据层负责 JSON 的加载、保存、备份;业务层负责任务的增删改查、排序、筛选;展现层负责表格渲染和统计输出。这样分层的好处是逻辑清晰,每一部分的代码量都不大,出了问题也容易定位。整个项目最终大概四百行左右,一个人维护完全没有压力。

2. 核心数据结构与存储方案

2.1 任务模型字段怎么设计

数据结构是整个项目的地基,设计得合理不合理,直接决定后续功能好不好写。我定义的任务模型包含八个字段:id(任务唯一标识)、title(标题,必填)、description(详细描述,可空)、priority(优先级,high/medium/low)、category(分类,默认“默认分类”)、due_date(截止日期,格式 YYYY-MM-DD)、status(状态,pending/completed)、created_at和completed_at(创建时间和完成时间,ISO 格式字符串)。

每个任务在程序里就是一个字典,所有任务放在一个列表里,整体结构是典型的“字典列表”。字段类型上我做了两项约束:优先级只允许三个枚举值,非法值直接拒绝写入;截止日期必须是合法日期,用datetime.strptime做了格式校验。这些约束看起来很简单,却能在源头上拦住大量脏数据。我做测试时真实遇到过用户手滑把截止日期输入成“2024/02/30”这种不存在的日期,没有校验的话,程序后面做排序会直接抛出异常。

排序规则上,待办列表的默认展示顺序是:未完成任务在前,已完成任务沉底;未完成任务内部按截止日期从近到远排列,截止日期相同则按优先级从高到低排;已完成任务按完成时间从新到旧排列。这个规则符合日常使用直觉——一眼就能看到最紧急的事。实现上就是用 Python 的sorted函数配合多级 key 元组,核心代码就只有几行。

2.2 JSON 文件读写与原子性保护

数据持久化我用了 JSON 文件,每次增删改操作后都会把整个数据列表写回文件。写入时有两个关键细节:ensure_ascii=False保证中文正常显示而不是变成\uXXXX转义序列,indent=2让文件在文本编辑器里打开也是工整可读的格式。我最早写的时候漏了ensure_ascii=False,打开 JSON 文件满屏的转义字符,那一刻真的觉得这个参数必须在任何涉及中文存储的 Python 脚本里成为肌肉记忆。

为了提升安全性,我额外做了原子写入保护:先把数据写入一个.tmp临时文件,写成功后再用os.replace原子替换原文件。这样就算程序在写入中途崩溃或者断电,原文件也不会变成半个 JSON 导致数据全丢。这个保护机制初期觉得有点多余,直到有一次我在 Windows 上强制结束进程,才发现正常直接写入确实有概率产生损坏文件。从此以后我所有涉及本地文件持久化的工具都用了同样的策略。

搜索功能也是基于 JSON 加载后的内存数据进行操作,支持在标题和描述两个字段里做不区分大小写的子串匹配。实现上就是列表推导式加in判断,简单直接。搜索是高频操作,实测几百条数据规模下响应是毫秒级的,完全不需要引入索引。

3. 实操过程与核心代码实现

3.1 环境准备:从 Python 安装到 rich 库

开始写代码前先把环境准备好。如果你机器上还没装 Python,我建议直接装 3.8 以上版本,我自己用的是 3.10 和 3.11 都测过,没有版本兼容问题。Windows 安装时有一个非常关键的步骤:必须在安装向导第一个界面勾选“Add Python to PATH”,否则装完之后在命令行里输入python会提示“不是内部或外部命令”。这个坑我帮人排查过无数次,九成都是因为当时没勾这个选项。

装完之后打开命令行,创建一个项目目录,然后安装rich库:

pip install rich

如果下载慢,可以加-i https://pypi.tuna.tsinghua.edu.cn/simple换国内镜像源。安装完可以用pip show rich验证是否成功,看到版本信息就说明环境齐了。有些同学用的是 Visual Studio Code 写 Python,那就再确认一下 VS Code 里选中的解释器是同一个 Python 环境,不然会出现“终端能跑,编辑器里跑不了”的奇怪问题。

3.2 命令行交互设计:短命令优先

交互方式我放弃了 argparse 这种传参风格,而是做成了一组极短的交互命令:输入add进入添加模式、list查看列表、done完成任务、edit编辑、del删除、find搜索、stats统计、quit退出。原因是命令行传参虽然看起来“正规”,但每天输十几个字符的指令确实麻烦。短命令更像在跟程序对话,使用成本低到不需要记忆。

主循环就是一个while True加input()分发。拿到用户输入后先去掉首尾空格再统一转小写,避免大小写不一致导致匹配不到命令。命令分发我用了if/elif链而不是字典映射,因为不同命令需要的后续参数数量不一样,用字典反而要把参数处理逻辑绕一圈。整个交互循环保持“读取—执行—刷新”的节奏,操作完自动重新打印一次任务列表,让用户立刻看到变化,这个体验细节我觉得很重要。

3.3 增删改查四个核心函数逐个实现

添加任务是使用频率最高的功能,我把它做成了分步询问式:先问标题,再依次问描述、优先级、截止日期、分类。每步都有默认值,直接回车就跳过,尽量降低输入负担。截止日期输入后会立即用datetime.strptime校验,格式错误就提示“请输入 YYYY-MM-DD 格式的日期,例如 2024-12-31”,然后重新询问,不会把脏数据写进文件。

标记完成和删除功能公用一个“按 ID 定位任务”的逻辑。任务 ID 由自增计数器生成,每次添加新任务时max(id) + 1。done命令执行时,先根据用户输入的 ID 找到任务,把状态改为completed并写入当前时间;已经完成的任务再次执行done会提示“该任务已完成,无需重复操作”。删除操作则直接把这个任务从列表里移除,同样要先校验 ID 是否存在,不存在时报错并打印当前所有未完成任务供用户参考。

编辑功能我用edit加 ID 的方式进入编辑流程:程序先把该任务的当前值逐个显示出来,用户直接回车表示该项保持不变,输入新内容则替换。这个“就地编辑”的模式比整条重新录入体验好很多,尤其适合只改一个截止日期或者只改一下优先级的情况。编辑完成后同样立即保存并刷新列表,整个编辑过程尽量控制在十秒内完成。

4. 表格渲染与交互体验优化

4.1 用 rich 把数据变成真正能看的表格

数据再多,如果显示得密密麻麻也没人愿意用。到这里rich库开始发挥作用。我创建了一个render_table(tasks)函数,接收任务列表,遍历每条任务插入表格行。表格列定义为:ID、状态、优先级、截止日期、分类、标题、描述。状态列用“进行中/已完成”两个中文词展示,比英文pending/completed直观太多。

优先级列做了颜色映射:高优先级红色加粗、中优先级黄色、低优先级绿色。这样打开列表的一瞬间,视觉焦点会自然落在最危险的任务上。截止日期列也有一个判断:如果任务还没完成且日期早于今天,就在日期后面加一个“已逾期”的红字标记。这个细节是我在真实使用过程中加的——有次我连续几天没看列表,重新打开才发现有个任务已经逾期三天了,纯文字日期根本勾不起紧迫感,加了这个标记后每天第一眼看列表都能立刻知道状况。

表格默认只显示未完成任务列表,已完成任务通过list done单独查看,避免主界面被历史数据刷屏。这个默认行为是我反复调整后才定下来的。一开始我全部显示,结果任务多了以后屏幕上全是旧任务,真正要处理的几件事反而被挤到下面去了。

4.2 排序、筛选与统计面板的完整实现

排序逻辑上方已经提到,核心代码是一个多级 key 的sorted。我单独写了一个sort_key(task)函数来把状态和截止日期转成可排序的值:未完成任务的状态值为 0,已完成为 1;优先级的排序值按 high=0、medium=1、low=2 映射,截止日期直接用字符串比较即可,因为 YYYY-MM-DD 格式的字典序就是时间序。用元组(status_order, due_date, priority_order, -id)作为排序键,四层排序一次搞定。

筛选功能我做了两个维度:按状态筛选和按优先级筛选。状态筛选对应list done/list todo/list all三个子命令;优先级筛选用filter high这种形式。两个维度可以组合使用,比如list todo filter high表示只看未完成的高优先级任务。组合筛选的实现很简单,就是先在内存里按状态过滤一次,再按优先级过滤一次,两个过滤条件依次叠加。

统计面板用stats命令呼出,输出内容包括总任务数、未完成数、已完成数、逾期任务数、完成百分比。百分比计算有个注意点:如果总任务数为 0,直接除会有除零错误,所以要提前判断total == 0时输出“暂无任务”。统计模块我顺便加了一条线性进度条:根据完成率算出#字符的数量,比如 20 个任务完成 14 个,进度条就是##############······ 70%。直接在终端里显示,看起来非常直观。

4.3 日期处理与跨平台中文乱码问题

日期相关的两个细节值得单独提出来讲。第一,截止日期和“今天”的比较要精确到日而不是时分秒,所以我在比较前统一把两个日期都通过.date()转成纯日期对象,避免“今晚 23:59 之前还算今天”这种边界问题。第二,用户偶尔会输入2024-12-1这种只有一位月份或日期的写法,我的校验函数里顺带做了规范化处理,把这类输入补全成YYYY-MM-DD再入库。

Windows 终端的中文乱码问题我在开发时也遇到了。解决方法是程序启动时执行sys.stdout.reconfigure(encoding='utf-8'),强制标准输出用 UTF-8 编码。在 Windows 上,Python 默认的输出编码有时是 GBK,rich 输出的制表符和中文混排就可能出现乱码。加上这句之后,实测 Windows 11 自带的 Terminal 和 Windows Terminal 都能正常显示。另外如果终端里仍然乱码,可以把终端代码页切到 UTF-8:先输入chcp 65001再运行程序。

5. 常见问题与排查技巧实录

5.1 JSON 文件被写坏或读取失败的应对

最典型的一类问题就是“程序启动时报 JSONDecodeError”。常见原因有三个:手动用记事本改文件时把格式改错了;程序写入中途断电或强制退出;多开了一个程序实例同时写入同一个文件导致互相覆盖。针对这个问题,我在加载数据时加了容错机制:如果 JSON 解析失败,自动把当前文件复制成todo_backup_时间戳.json再尝试加载,同时打印提示“数据文件疑似损坏,已创建备份,请检查备份或手动修复”。如果连备份也没有,就从空列表启动,绝不让程序直接崩溃退出。

5.2 命令行里 python 命令不可用

这个现象九成出在 Windows 上刚装完 Python 的新手阶段。要么是安装时没勾选“Add Python to PATH”,要么是安装后没有重新打开命令行窗口导致环境变量没生效。解决办法一个是重新安装一遍 Python 并勾选 PATH 选项,另一个是在命令行执行set PATH=%PATH%;你的Python安装目录临时加入路径。VSCode 用户还要额外确认右下角状态栏显示的 Python 解释器路径,是不是跟系统命令行用的是同一个。

5.3 表格在窄窗口里显示错位

rich 的表格会自动适配终端宽度,但如果你开的窗口特别窄,长标题还是可能被截断或者换行导致看起不整齐。我处理这个问题的策略是:给标题列设置max_width=30,超长内容自动截断加省略号;描述列设置overflow='fold',超出宽度自动换行而不是切断。这样实际使用下来,即使把终端拖到只剩半屏,表格各列也不会挤成一团。另外明确建议用户优先使用 Windows Terminal 而不是老版控制台,字体和制表符支持都更好。

5.4 误操作导致任务被删,能否恢复

关于误删恢复这件事,我的建议是:把“删除”设计为二次确认操作。我在del命令里加了确认提示:“确定要删除 ‘任务标题’ 吗?输入 y 确认,其他任意键取消。”这个确认虽然多了一步操作,但真的能挡住脑子一热输错 ID 的情况。我自己有一次想删 ID 5 结果敲成了 6,那次之后我就再没取消过二次确认。如果确实误删了,还可以手动从每日自动备份的 JSON 文件里恢复,我额外加了一个“每天首次启动时自动备份一份数据文件”的机制,文件保留最近 7 天。

5.5 数据量变大后有没有性能问题

待办事项这种场景,数据量到一万条以上才有可能感觉到轻微延迟。我用 5000 条假数据实测过:加载 JSON 文件约 0.2 秒,list表格渲染约 0.3 秒,搜索和排序都是毫秒级,体感完全流畅。如果你是那种“把两年前的任务都留着不删”的人,顶多也就几千条,完全不用担心性能。真到十万条级别,我会选择迁移到 SQLite 而不是继续用 JSON,但那是另一个项目的话题了。

这个项目后续还能怎么长

代码写完到今天我已经连续用了两个月,每天上班第一件事就是打开终端敲python todo.py,看一眼列表然后开始干活。这个工具真正改变了我对待办管理的习惯——它足够轻、足够快、数据在自己手里,没有广告没有弹窗,比任何在线待办应用都可靠。

如果你也想照着写一个,我的建议是不要照抄代码,而是先把需求列清楚,想清楚自己要哪几个功能、砍掉哪几个功能,再动手。写的过程中特别注意数据校验和文件安全性这两块,它们看着不起眼,却是决定工具能不能长期使用的关键。扩展方向上,你可以试试把数据换成 SQLite、加一个简单的 Web 界面,或者做一个每天上午 9 点自动打印当日待办的定时任务,这些都是很自然的下一步。工具不在大,在于每天愿意打开它。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询