利用argparse模块开发带复杂参数的命令行程序

目录

背景

最近看了一些 ecFlow 的文档,与目前我们正在用的 SMS 相比有不少优点,其中一点就是 ecFlow 提供一个统一的客户端命令行程序 ecflow_client,替代之前的一组 sms 命令

和 cdp 命令接口。之前的用过 cdp 接口,感觉虽然比 ecflow_client 的命令短,但很难在线获得帮助信息,有时解析失效,不太好用。ecflow_client 尽管需要输入更多的信息,但胜在有详细的帮助信息,总体上来说更加方便易用。
ecflow_client 类似 git 等命令行程序,将多个子命令组合到一起,通过选项区分。
git 命令举例:

ecflow_client 命令举例:

我对这种命令行程序设计方式很感兴趣,就想到模拟 ecflow_client,为 SMS 创建一个简单的客户端接口,实现我平时用到的几个 cdp 命令功能:加载 def 文件、替换节点、删除节点。

需求

一个客户端程序,根据选项实现不同的子命令功能,每个子命令可能有不同的命令行参数,也有通用的命令行参数。

实现

Python 的 argparse 模块提供构建复杂命令行参数的功能,可以满足上述需求。

通用参数

SMS 客户端命令需要登录到 SMS 服务器后才能运行,所以所有的子命令都需要 SMS 服务器主机名和用户名这两个参数。
argparse 提供共享参数解析器的机制,在创建解析器时可以设置 parents 解析器列表,列表中每个解析器的参数都会添加到新创建的解析器中。所以先创建主机和用户名的解析器。

注意,不要引入重复参数,所以要设置 {py}add_help=False{/py},防止通用解析器自动添加 help 参数。

子命令

sms_client 以不同的子命令提供不同的功能,argparse 模块通过 ArgumentParser.add_subparsers 支持子命令。
创建 sms_client 的参数解析器

添加子命令解析器

用户选用某种子命令后,该子命令名会保存在 dest 属性设置的变量中,也就是 sub_command 变量中,后续程序可以根据 sub_command 的值执行不同的操作。
添加不同的子命令

参数解析

使用 parse_args() 解析参数,返回解析后的结果。

根据子命令执行对应的操作

运行示例

命令帮助

子命令帮助