简介这是一份面向 Python 初学者的命令行待办事项练习资源帮助读者在本地环境中通过实现增删任务、保存与加载数据等核心功能掌握函数封装、文件读写与 CLI 交互的基本思路。压缩包共 7 个文件约 295KB包含 2 个 py 脚本分别承载应用主逻辑与测试用例1 个 json 与 1 个 csv 用于任务数据的持久化存储另有 md 说明文档、gitignore 配置及 gif 演示动图结构精简、开箱即用。资源围绕 add_one_task、print_list、delete_task、save_todos、load_todos 五个待实现函数展开读者可先运行测试脚本验证进度再启动主程序体验完整流程逐步理解命令行参数解析、列表增删与文件序列化的配合方式。目前已有 355 人学习适合作为 Python 基础语法与小型项目实战的衔接练习也可用于课堂作业或自学打卡。1. 从一团乱麻到一条命令这个待办工具到底能帮你做什么你有没有过这种时刻脑子里同时压着七八件事写下来怕丢不写又一直惦记手机备忘录翻半天找不到重点最后干脆靠脑子硬扛结果漏了一件被追问时才想起来。更麻烦的是很多在线待办工具要注册、要联网、要同步你只是想安安静静记个事却先被引导着走完一套流程。这份 Exercise-todo-list-cli-python 就是冲着这种场景来的它是一个用 Python 写的、只在本地跑的待办事项列表命令行工具不联网、不注册、不弹窗打开终端敲一行命令就能记、能看、能勾掉。它适合刚学 Python、想找一个能真正跑起来的小项目练手的人也适合只想把待办管明白、不想被工具绑架的人。你不需要先懂什么高深概念只要电脑上有 Python就能跟着往下走。2. 为什么值得从它入手先搞懂命令行待办这件事2.1 它和手机备忘录到底差在哪很多人第一次听到「命令行待办」会本能地皱眉黑底白字是不是很难用其实你可以把它想成一个只认文字的抽屉。手机备忘录像一个大杂物箱什么都能塞但找起来靠翻命令行待办更像一排贴了标签的小格子你每次只做一件事——放进去、看一眼、划掉。它的优势不在花哨而在快和稳不用等 App 启动不用登录不用同步敲完回车结果立刻出现。对新手来说这种「输入什么就得到什么」的反馈特别重要因为你能清楚看到自己写的代码到底干了什么而不是被一层层界面挡住。它解决的核心问题就一个把「记下来」这件事的成本降到几乎为零让你愿意真的去记。2.2 为什么用 Python 写待办最合适Python 在这类小工具上有天然优势。第一语法接近自然语言读起来不费劲你不需要先啃一堆符号才能看懂逻辑。第二标准库自带处理文件和列表的能力待办数据存本地、读本地几行代码就能搞定不用装额外框架。第三命令行交互用内置的 input 和 print 就能完成新手不会被图形界面、网络请求这些额外概念劝退。换句话说这个项目把「学 Python」和「做一个有用的小东西」绑在了一起你写的每一行都有明确目的不是为练习而练习。我第一次带人入门时发现凡是能当天跑出结果的小项目坚持率远高于纯看语法。待办列表正好属于这一类——门槛低但完整覆盖了变量、列表、循环、条件判断、文件读写这些核心知识点。2.3 先看清它的边界仅限本地意味着什么标题里「仅限本地」四个字很关键它不是缺点而是定位。数据存在你自己电脑的一个文件里不经过任何服务器所以没有账号、没有云端、没有多人协作。好处是简单、私密、离线可用代价是换电脑要手动拷文件多人共享得自己想办法。对入门阶段来说这恰恰是优点你不需要理解网络、数据库、并发这些还没学的东西就能把整个流程跑通。等你把这个本地版本吃透了再去扩展成联网版心里会有底得多。所以别一上来就想着「能不能同步到手机」先把本地这条链路走顺才是新手最该做的事。3. 动手第一步把第一个待办跑起来3.1 动手前先确认两件事在写任何代码之前先确认你的电脑上装了 Python并且能在终端里调用它。打开终端Windows 用 PowerShell 或 CMDmacOS 和 Linux 用系统自带的终端输入下面这行命令python --version如果显示类似 Python 3.x.x 的字样说明环境没问题。如果提示找不到命令可以试试把 python 换成 python3 再输一次。这一步看着简单却是新手翻车最多的地方——很多人后面代码报错其实根源是 Python 根本没装好或者没加进环境变量。确认版本在 3.6 以上就够了这个项目用不到太新的特性。接着找一个你放代码的文件夹比如在桌面上新建一个 todo 目录后面所有文件都放这里避免文件散落各处找不到。3.2 第一个能跑的版本只做「添加」和「查看」先别急着写完整功能新手最容易犯的错是一上来就想把增删改查全写完结果卡在中间失去信心。我们分步来第一个版本只做两件事添加待办、查看待办。新建一个文件命名成 todo.py写入下面的代码# 用一个列表在内存里暂存待办事项 todos [] while True: # 打印菜单让用户知道能做什么 print(\n1. 添加待办 2. 查看待办 3. 退出) choice input(请输入选项数字) if choice 1: # 读取用户输入的内容并追加到列表 item input(要添加什么) todos.append(item) print(已添加, item) elif choice 2: # 遍历列表按序号打印出来 if not todos: print(还没有待办事项) else: for index, item in enumerate(todos, start1): print(f{index}. {item}) elif choice 3: print(再见) break else: print(请输入 1、2 或 3)这段代码的逻辑很直白todos 是一个列表用来装待办while True 让程序一直循环直到你选退出input 负责接收你的输入append 把新事项塞进列表enumerate 在打印时自动加上序号。运行方式是回到终端进入文件所在目录输入python todo.py然后按提示操作添加几条、查看一下、再退出。如果你能顺利走完这一圈恭喜你已经跑通了最核心的交互骨架。这里的关键参数是 start1它让序号从 1 开始而不是默认的 0对使用者更友好这个细节虽小但体现了「工具是给人用的」这个思路。3.3 让待办活下来把数据存进本地文件上面那个版本有个致命问题一退出待办全没了因为数据只在内存里。要让它真正有用必须写进本地文件。我们加两个函数一个负责读一个负责写import json import os FILE_NAME todos.json def load_todos(): # 文件不存在就返回空列表避免第一次运行报错 if not os.path.exists(FILE_NAME): return [] with open(FILE_NAME, r, encodingutf-8) as f: return json.load(f) def save_todos(todos): # 每次改动后整体写回文件 with open(FILE_NAME, w, encodingutf-8) as f: json.dump(todos, f, ensure_asciiFalse, indent2)然后在程序开头把 todos [] 换成 todos load_todos()在每次添加之后调用 save_todos(todos)。这里用 JSON 格式存是因为它既能被 Python 直接读写又能用文本编辑器打开看出问题时方便排查。ensure_asciiFalse 保证中文正常显示而不是变成一串编码indent2 让文件内容有缩进、便于阅读。encodingutf-8 则是防止中文在不同系统上乱码。做完这一步你退出再重新运行之前添加的待办还在这个工具才算真正立住了。4. 把功能补全删除、完成与更顺手的交互4.1 加上删除和标记完成一个只能加不能删的待办列表用两天就会变成垃圾场。我们给每个待办加上「是否完成」的状态并支持删除。把原来存字符串的列表改成存字典# 每条待办是一个字典包含内容和完成状态 todos.append({text: item, done: False})查看时根据 done 显示不同标记for index, todo in enumerate(todos, start1): mark [x] if todo[done] else [ ] print(f{index}. {mark} {todo[text]})再增加两个菜单项一个用来切换完成状态一个用来删除elif choice 4: num int(input(要标记完成的序号)) todos[num - 1][done] True save_todos(todos) elif choice 5: num int(input(要删除的序号)) todos.pop(num - 1) save_todos(todos)注意 num - 1 这个减法用户看到的是从 1 开始的序号而列表下标从 0 开始不减一就会删错或越界。这是新手极容易忽略的一处写的时候心里默念「给人看从 1 起给程序用从 0 起」能省下不少调试时间。4.2 处理输入错误别让程序一崩了之上面那段代码有个隐患如果用户在要求输入序号时敲了字母int() 会直接抛异常整个程序崩掉。真实使用中这种事几乎必然发生所以必须加保护try: num int(input(要删除的序号)) todos.pop(num - 1) save_todos(todos) except (ValueError, IndexError): print(序号无效请重新输入)try 负责尝试执行可能出错的代码except 负责接住错误并给出友好提示。ValueError 对应「输入的不是数字」IndexError 对应「序号超出范围」。把这两个都接住程序就不会因为一次误输入而退出。这种「先想哪里会错再决定怎么兜住」的习惯比多写几个功能更能提升代码质量也是从新手走向能用的分水岭。4.3 用参数让命令更利落每次运行都进菜单点来点去用久了会嫌慢。可以借助 sys.argv 支持直接带参数执行比如 python todo.py add 写周报 就添加一条python todo.py list 就列出全部。核心是读取命令行参数import sys if len(sys.argv) 1: command sys.argv[1] if command add and len(sys.argv) 2: todos.append({text: sys.argv[2], done: False}) save_todos(todos) print(已添加) elif command list: for index, todo in enumerate(todos, start1): mark [x] if todo[done] else [ ] print(f{index}. {mark} {todo[text]})sys.argv 是一个列表第 0 个是脚本名后面依次是你敲的参数。这样你就能把常用操作压缩成一行命令甚至写进快捷方式。对新手来说这一步的价值不只是「更方便」而是让你第一次体会到「程序可以被别人用不同方式调用」这是理解接口概念的起点。5. 新手避坑这几个地方最容易卡住5.1 现象运行报错「No such file or directory」原因终端当前所在目录和你存放 todo.py 的目录不一致程序找不到文件或者读写 todos.json 时路径对不上。解决先用 cd 命令切到文件所在目录再运行 python todo.py如果还是不行用 pwdWindows 用 cd确认当前位置必要时用绝对路径。养成「先看自己在哪再运行」的习惯能省掉大量莫名其妙的报错。5.2 现象中文显示成乱码原因文件读写时没有指定编码系统默认编码和你的内容不匹配。解决所有 open() 都加上 encodingutf-8json.dump 加上 ensure_asciiFalse。这两处一加中文基本不会再出问题。如果终端本身显示乱码那是终端编码设置的事和代码无关换个支持 UTF-8 的终端即可。5.3 现象删除了错误的待办或者程序提示下标越界原因忘了把用户看到的序号减一或者用户输入的序号超过了列表长度。解决统一在取值时做 num - 1并用 try/except 接住 IndexError更稳妥的做法是先判断 1 num len(todos) 再操作。序号转换是命令行工具里最经典的坑几乎每个人都会踩一次。5.4 现象改了代码但运行结果没变原因要么文件没保存要么运行的是另一个同名文件要么 Python 缓存了旧版本。解决先确认编辑器已保存再确认终端里运行的路径正确必要时关掉重开终端。这类问题不涉及逻辑纯粹是环境问题但特别消耗新手信心遇到时先别怀疑自己代码写错了。5.5 现象数据文件被写坏待办全丢原因程序在写入过程中被强制中断JSON 文件只写了一半。解决写入前先把内容写到临时文件成功后再替换原文件或者每次改动前手动备份一份 todos.json。对入门项目来说手动备份就够用但要有这个意识——数据一旦丢了没有后悔药可吃。6. 下一步往哪走从能跑到好用把上面这些跑通之后你手里已经有一个能真正用的本地待办工具了。接下来别急着加花哨功能先按下面的路径把基础打牢。第一步把代码拆成函数现在所有逻辑挤在一个 while 里读起来累改成 add_todo、list_todos、delete_todo 这样的独立函数每个只干一件事主循环只负责调度。这一步能让你第一次理解「模块化」到底在解决什么问题。第二步加上截止日期和优先级给每条待办多存两个字段查看时按优先级排序这会把列表、字典、排序这几个知识点串起来。第三步学一点测试给核心函数写几个简单断言改代码后跑一遍确认没把原来的功能弄坏。第四步如果你还有兴趣再考虑把它包装成可以用 pip 安装的命令行工具那时候你会自然接触到项目结构和打包而不是被硬塞概念。阶段目标涉及知识点拆分函数代码可读、可维护函数定义、参数、返回值加字段支持日期与优先级字典、排序、日期处理写测试改动不破坏旧功能断言、测试思路打包像正式工具一样安装项目结构、入口配置我自己的血泪经验是每次加新功能前先把当前版本完整跑一遍确认基线是好的再去动代码。这样一旦出问题你能立刻知道是新改动引起的而不是在一堆变化里大海捞针。从那以后我每次动手前都强制走一遍这个确认流程省下的调试时间远比那几分钟多。希望这份入门路径能帮到你先从第一个能跑的版本开始别贪多跑通比写完更重要。本文还有配套的精品资源点击获取