ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

【Python项目实战】项目·命令行待办清单:文件读写 + JSON持久化

【Python项目实战】项目·命令行待办清单:文件读写 + JSON持久化 本篇成果一个命令行待办清单。添加、查看、完成、删除数据存进文件关掉终端重开还在。含注释120行左右五脏俱全没有一行多余。 太长不看版给想直接看代码的你项目信息一句话说明项目名称命令行待办清单Todo CLI代码行数~120行含注释依赖零依赖全部Python自带模块核心功能增删改查 JSON持久化跑起来的命令python main.py add 写一篇笔记技术点argparse、json、pathlib、strftime做完你能得到第一个“关掉终端再开数据还在”的程序一、成品预览先看我们要做什么$ python main.py add 给专栏写一篇笔记 已添加给专栏写一篇笔记 $ python main.py add 复习第3篇的venv命令 已添加复习第3篇的venv命令 $ python main.py list 1. ⬜ 给专栏写一篇笔记2026-09-01 20:00 2. ⬜ 复习第3篇的venv命令2026-09-01 20:01 —— 已完成 0/2 —— $ python main.py done 1 完成给专栏写一篇笔记 $ python main.py list 1. ✅ 给专栏写一篇笔记2026-09-01 20:00 2. ⬜ 复习第3篇的venv命令2026-09-01 20:01 —— 已完成 1/2 —— $ python main.py del 2 已删除复习第3篇的venv命令 $ python main.py list 1. ✅ 给专栏写一篇笔记2026-09-01 20:00 —— 已完成 1/1 ——关键卖点只有一个关掉终端明天再开list一敲数据还在。这叫持久化——之前你写的一切脚本都是“运行即失忆”从今天起你的程序有了记忆。 为什么选待办清单当第一个项目理由说明功能小一晚上跟得完不劝退覆盖全增删改查 文件读写 命令行参数 企业级应用的骨架零依赖全部用Python自带模块不装任何第三方包能复用学完这个后面FastAPI版的待办清单第23篇你会看到同一个需求怎么“长大”二、前置知识两分钟补两块砖 JSON人能读懂的数据格式就是长这样的文本文件和Python的列表/字典几乎一一对应[{text:给专栏写一篇笔记,done:true,created:2026-09-01 20:00},{text:复习第3篇的venv命令,done:false,created:2026-09-01 20:01}]函数作用json.loads(文本)JSON文本 → Python对象json.dumps(对象)Python对象 → JSON文本 两个注意JSON的列表对应[]、字典对应{}ensure_asciiFalse参数能让中文原样保存而不是变成\u4e2d\u6587。 pathlib现代的文件操作第5篇见过的Path本篇用到三个技能用法作用Path(todos.json)定位文件在当前目录.exists()判断文件是否存在.read_text()/.write_text()读写文本内容 有了这两块砖开工三、第0步3分钟项目setup前5篇的复习按第5篇模板建项目一气呵成1. 新建文件夹 todo_projectVSCode打开File → Open Folder 2. python -m venv venv # 零依赖也建venv习惯要从第一个项目养成 3. 激活windows: venv\Scripts\activatecmd | .\venv\Scripts\Activate.ps1PowerShell mac: source venv/bin/activate 4. git init写好.gitignorevenv/ 和 __pycache__/ 5. 新建空文件main.py 有同学问为什么不分utils/故意的。第一版先把它写“歪”后面复盘时我们亲手把它拆开重构——到时候你会真正明白“为什么要拆”而不是背口诀。四、第1步设计数据结构写代码前先想清楚一条待办长什么样三个字段内容、状态、创建时间。整个清单就是这样的列表# 概念示意不用敲[{text:给专栏写一篇笔记,done:false,created:2026-09-01 20:00},{text:复习第3篇的venv命令,done:false,created:2026-09-01 20:01}]先定结构再动手是和想到哪写到哪的第一个分水岭。之后所有函数都围绕这个结构工作——结构即契约第9节报错⑤会让你见识破坏契约的后果。五、第2步存与读——程序的记忆todo —— 命令行待办清单 v1importjsonimportargparsefrompathlibimportPathfromtimeimportstrftime DATA_FILEPath(todos.json)# 数据文件就放项目根目录defload_todos():读数据第一次使用文件不存在返回空列表ifDATA_FILE.exists():returnjson.loads(DATA_FILE.read_text(encodingutf-8))return[]defsave_todos(todos):把列表写回文件ensure_asciiFalse让中文原样保存textjson.dumps(todos,ensure_asciiFalse,indent2)DATA_FILE.write_text(text,encodingutf-8) 两个细节细节为什么重要encodingutf-8Windows默认编码是GBK不加中文乱码第2篇的老规矩indent2把文件排版成带缩进的人类可读格式——你可以用VSCode直接打开看六、第3步四个功能每个10行以内添加defadd_todo(text):todosload_todos()todos.append({text:text,done:False,created:strftime(%Y-%m-%d %H:%M)})save_todos(todos)print(f已添加{text})查看列表deflist_todos():todosload_todos()ifnottodos:print(清单是空的来一条python main.py add 学Python)returnfori,tinenumerate(todos,start1):flag✅ift[done]else⬜print(f{i}.{flag}{t[text]}{t[created]})done_countsum(1fortintodosift[done])print(f—— 已完成{done_count}/{len(todos)}——)标记完成defcomplete_todo(index):todosload_todos()try:ttodos[index-1]# 用户编号从1开始列表下标从0开始exceptIndexError:print(f没有第{index}条先用list看看)returnt[done]Truesave_todos(todos)print(f完成{t[text]})删除defdelete_todo(index):todosload_todos()try:ttodos.pop(index-1)exceptIndexError:print(f没有第{index}条)returnsave_todos(todos)print(f已删除{t[text]}) 注意每个函数都是同一个节奏读 → 改 → 存 这个“读改存”循环就是所有数据类应用的原子结构——从待办清单到银行系统骨架不变变的只是规模。⚠️index - 1是新手的经典坑编号从1开始给人看下标从0开始给程序用第9节③专门讲它。七、第4步argparse接上命令行最后一块让程序听懂add、list这些指令。defmain():parserargparse.ArgumentParser(description命令行待办清单)subparser.add_subparsers(destcommand,requiredTrue)psub.add_parser(add,help添加一条待办)p.add_argument(text,help待办内容带空格请加引号)sub.add_parser(list,help查看全部待办)psub.add_parser(done,help标记完成)p.add_argument(index,typeint,help编号见list输出)psub.add_parser(del,help删除待办)p.add_argument(index,typeint,help编号见list输出)argsparser.parse_args()ifargs.commandadd:add_todo(args.text)elifargs.commandlist:list_todos()elifargs.commanddone:complete_todo(args.index)elifargs.commanddel:delete_todo(args.index)if__name____main__:main() 两个关键点知识点说明sub.add_parser给程序装“子命令”add、list各管各的typeintargparse自动把用户输入转成整数转换失败会替你报错if __name__ __main__第5篇说的“入口仪式”直接运行才执行八、第5步验收清单保存main.py然后逐条跑python main.py add 给专栏写一篇笔记 python main.py add 复习第3篇的venv命令 python main.py list python main.py done 1 python main.py list python main.py del 2 python main.py list✅ 最终验收关掉终端重开再list一次——数据还在持久化验收通过用VSCode打开todos.json看一眼这就是你程序的“记忆”长什么样。 提交Git验收通过按第4篇流程存档gitadd.gitcommit-m完成待办清单v1增删改查 JSON持久化 你的GitHub上从此多了一个完整项目。九、常见报错这6个都是新手第一次写项目的真实坑重点① 打印✅时报UnicodeEncodeError: gbk codec cant encode character 原因老式Windows终端默认GBK编码装不下emoji。✅ 解法二选一终端执行chcp 65001切UTF-8第6篇⑤的回旋镖把代码里的✅⬜换成[√][ ]一劳永逸。②json.decoder.JSONDecodeError: Expecting value 原因todos.json的内容不是合法JSON——多半是你手动编辑时删了个逗号/括号或者文件被改成了空文件。✅ 解法打开文件找语法错少逗号、多括号救不回来就删掉文件重新来你的程序会自动重建。 顺便体会数据文件是程序的命根改它要像改代码一样谨慎。③ done的编号总是差一位 原因你在自己的代码里写了todos[index]而不是todos[index - 1]。界面上给用户看的编号从1开始Python列表下标从0开始——这叫off-by-one错误程序员的百年老坑。✅ 解法定位这一行的最好办法——用第6篇的断点看看index和实际点到的元素差在哪。④add 去超市存进去只剩“去” 原因终端把空格当成参数分隔符去和超市被切开了。✅ 解法带空格的内容加引号python main.pyadd去超市买牛奶# ✅ 正确python main.pyadd去超市买牛奶# ❌ 只存了去 Windows的cmd/PowerShell都认双引号。⑤KeyError: done 原因你手动编辑todos.json时删了某个字段。程序依赖的结构被破坏了——还记得第4节说的“结构即契约”吗。✅ 解法把字段补回去以后想改数据结构改代码和改数据要同步。⑥ 只敲了python main.py add蹦出一堆红字报错内容error: the following arguments are required: text 原因这不是崩溃是argparse在拦你——你少传了参数它把正确用法usage都打印出来了。✅ 解法照着usage提示补上参数。学会读argparse的自动提示它写的说明书比你想象的细。十、课后练习做了才算会#练习难度提示1加一个clear命令一键删除所有已完成项⭐⭐列表推导式[t for t in todos if not t[done]]sub.add_parser2给“完成”加时间戳done时记done_atlist里已完成项显示完成时间⭐⭐⭐修改complete_todo函数加字段3按流程把本项目推上GitHub按模板补README⭐⭐你的第一个“完整项目”简历上可以写的那种4选做把统计行改成进度条[####------] 已完成2/5⭐⭐⭐# * n - * (5-n) 配套代码完整main.py、示例数据与README已上传GitHub07-todo-cli/todo_project【https://gitee.com/xqshadow/python-project-in-practice】
返回列表