读懂一个 186 行 Python CLI 工具:从敲命令到理解每一行
开篇
我最近写了一个 workspace manager,一个命令就能打开某个任务需要的全部软件。比如做 CAD 设计,python workspace.py design 一键同时启动 AutoCAD 和 Photoshop,不用一个个手动开。
186 行代码,纯 Python 标准库,跑通了。但我不想停在”能用就行”,而是想彻底搞懂每一行为什么这么写。这篇文章记录我学到的 6 个知识点。
这脚本是干嘛的
做设计的日常:开机 → 打开 AutoCAD → 打开 Photoshop → 开始干活。每天重复。能不能一句话搞定?
1 | python workspace.py design |
AutoCAD 和 Photoshop 同时启动,像 IDE 保存项目标签页一样,只不过是在操作系统层级。
1 | # 创建工作空间 |
配置存在 ~/.workspaces.json,长这样:
1 | { |
整体架构:一眼看到底
整个程序的骨架就一句话:CLI 工具 = 命令分发器。用户敲命令 → 解析 → 分发给对应函数执行。
看主函数最后这 7 行:
1 | { |
字典的 key 是命令名,value 是函数对象。取出来,后面加 (args) 直接调用。这就是 Python 版的 switch-case —— C 里得写一长串 if-else if,Java 得更啰嗦,Python 一个字典搞定,干净利落。
命令行参数解析:argparse 怎么把字符串变成结构体
1 | python workspace.py create dev "开发环境" |
args 是 argparse 自动构造的 Namespace 对象,跟 C 的 struct 一个概念——把命令行字符串变成有名字的字段:
1 | // C 里你会这样 |
Python 里 add_argument 就是声明字段,argparse 帮你填值:
1 | subparsers = parser.add_subparsers(dest="command") # → args.command |
参数多了你不用手写解析逻辑,库全包了。
程序的记忆:JSON 持久化
没有 JSON 文件,程序一关,你建的 workspace 全丢了。每次运行都得重新 add 一遍软件——那还不如手动开。
JSON 是这个程序的”记忆”。启动时读记忆,结束时存记忆:
1 | CONFIG_PATH = Path.home() / ".workspaces.json" |
所有操作都是 读文件 → 改字典 → 写文件 三步:
1 | 用户敲命令 → load_config() → 在内存字典里增/删/改 → save_config() → 程序退出 |
Path.home() 跨平台取用户目录,Windows 是 C:\Users\你的用户名,macOS 是 /Users/你的用户名。配置文件放这里不会被 git 跟踪到,也不会跟项目代码混在一起。
启动软件的两种姿势
Windows 上打开东西分两种情况:
1 | ext = os.path.splitext(path)[1].lower() |
.exe 程序文件 → 自己跑起来,所以用 subprocess.Popen,新开一个进程执行。
.docx / .pdf 文档文件 → 自己不运行,是让关联程序打开它。os.startfile 等价于你在资源管理器里双击文件,Windows 自动找 Word 或 PDF 阅读器代开。
subprocess.Popen(cmd, shell=True) 怎么理解?shell=True 就是交给 Windows 的 cmd 去解释命令字符串。跟 C 语言里 system("notepad.exe") 干的是一模一样的事——调操作系统帮你启动程序。区别是 Popen 可以拿到进程对象,不阻塞当前脚本,更灵活。
最巧妙的技巧:偷偷帮你补全命令
这是 186 行里我最喜欢的设计。看这段:
1 | COMMANDS = {"create", "delete", "list", "show", "add", "remove", "launch"} |
思路:如果用户敲的第一个词不是已知命令,就当他是在说 workspace 名字,自动在前面塞一个 "launch"。
1 | 用户输入: python workspace.py design |
少打 launch 六个字符,体验直接起飞。这是在 argparse 解析之前偷偷改了 sys.argv,把输入”骗”成合法格式。
收获
186 行代码,吃透后学到 6 样东西:
| # | 知识点 | 关键 |
|---|---|---|
| 1 | 命令分发 | 字典映射函数 = Python 的 switch |
| 2 | argparse | 命令行 → 结构体,字段即参数 |
| 3 | JSON 持久化 | 程序的”记忆”,读-改-写三步 |
| 4 | Popen + startfile | 程序自己跑,文档找人代开 |
| 5 | shell=True | 跟 C 的 system() 一回事 |
| 6 | argv 前置注入 | 解析前动手脚,省用户打字 |
最重要的领悟是:代码不是跑起来就行,读懂设计意图才算真的掌握。 你多学到的每一点,下次自己写代码时都会冒出来帮你。
















