12
小项目:命令行待办事项工具
Mini Project: CLI Todo
前面学的零件,凑一个真东西出来。需求:命令行里加待办、列待办、勾选完成、删除;数据存 JSON 文件,下次打开还在;用 argparse 解析命令。代码不长,但涵盖了文件 IO、JSON、argparse、数据结构、函数——综合练手。
完整代码 todo.py
import argparse
import json
from pathlib import Path
# 数据存哪:脚本同目录下的 todos.json
DATA_FILE = Path("todos.json")
def load_todos():
"""读文件,文件不存在就返回空列表"""
if not DATA_FILE.exists():
return []
with open(DATA_FILE, encoding="utf-8") as f:
return json.load(f)
def save_todos(todos):
"""把列表写回 JSON"""
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(todos, f, ensure_ascii=False, indent=2)
def cmd_add(args):
todos = load_todos()
todos.append({"task": args.task, "done": False})
save_todos(todos)
print(f"已添加:{args.task}")
def cmd_list(args):
todos = load_todos()
if not todos:
print("(空)啥也没有,天下太平。")
return
for i, t in enumerate(todos, 1):
mark = "[x]" if t["done"] else "[ ]"
print(f"{i}. {mark} {t['task']}")
def cmd_done(args):
todos = load_todos()
if 1 <= args.id <= len(todos):
todos[args.id - 1]["done"] = True
save_todos(todos)
print(f"已完成:{todos[args.id-1]['task']}")
else:
print("编号不对,先 list 看看。")
def cmd_del(args):
todos = load_todos()
if 1 <= args.id <= len(todos):
removed = todos.pop(args.id - 1)
save_todos(todos)
print(f"已删除:{removed['task']}")
# 命令行解析器:定义子命令 add / list / done / del
def main():
parser = argparse.ArgumentParser(description="命令行待办")
sub = parser.add_subparsers(dest="command", required=True)
p_add = sub.add_parser("add", help="添加待办")
p_add.add_argument("task")
p_add.set_defaults(func=cmd_add)
p_list = sub.add_parser("list", help="列出全部")
p_list.set_defaults(func=cmd_list)
p_done = sub.add_parser("done", help="标记完成")
p_done.add_argument("id", type=int)
p_done.set_defaults(func=cmd_done)
p_del = sub.add_parser("del", help="删除一条")
p_del.add_argument("id", type=int)
p_del.set_defaults(func=cmd_del)
args = parser.parse_args()
args.func(args)
if __name__ == "__main__":
main()
怎么用
python3 todo.py add "买牛奶"
python3 todo.py add "写周报"
python3 todo.py list
# 1. [ ] 买牛奶
# 2. [ ] 写周报
python3 todo.py done 1
python3 todo.py list
# 1. [x] 买牛奶
# 2. [ ] 写周报
__name__ == "__main__" 是干嘛的
这行的意思是:"只有直接运行这个文件时才执行 main();被别的文件 import 时不要执行"。Python 文件被 import 时,__name__ 是模块名;直接运行时,__name__ 是 "__main__"。这是 Python 的标准写法,照抄就行。