CLI工具编写的一点技巧
编写命令行工具的一点心得
命令行工具在开发过程中有一些痛点:
- 命令的设计与识别:
- 当用户输入参数的时候如何去识别用户的意图
- 如何在编写的时候更优雅的组织代码
解决方法:
为命令制定规范,设计时首先要满足一些非硬性要求
https://zhuanlan.zhihu.com/p/47312390
- 良好的帮助命令是必不可少的
- 倾向于使用选系代替参数
- 明确当前的版本(一般是 –version/-V)
- 关注流处理(输入输出流和重定向)
- 处理错误
- 尽量提示
- 使用表格(组织好输出,使美观)
- 唯快不破(工具效率)
- 清晰的子命令
- 用户能够自己设置一些配置
以上是参考文章提炼出的一点对工具功能开发,命令设计的一些抽象原则,再说一下个人总结的一些命令规范以及解决的问题
- 识别命令目的(本方案采用 ‘docopt’ 获取命令行参数)
- 命令在设计时,一般都是 program action [args…][flags…]
- 代码文件分为两类,一类是路径文件,用于分析命令参数来确认命令目的,一类是功能文件,用于实现命令功能
- 命令的分层,以及功能代码的粒度
- 命令需要分层,可以把命令想象成一棵树,根节点就是我们的program,子节点是action,当然,子节点还有可能有子节点
- 命令树的划分原则,什么样的节点需要继续划分
当节点划分至make 时,我们发现,若make的下一层子命令的第一个值为model1时,对应args1,当自命令为model2时,子命令为args2,这样的节点我们称之为“歧义节点”,这样的节点需要继续划分,我们的功能代码文件里应该实现的是program make model1的功能,而不应该让区分用户想要做什么的过程出现在功能文件里program make model1 [args1...]
model2 [args2...]
- 实现原理
program -h
program do -h
program do thing1 [args1...|-h]
program do thing2 [args2...|-h]
program dothing [flags...|-h]
代码
cli.py
commands =['do','dothing']
if argv[1] in commands:
# 如果cmd = program do thing1 args...,f = open('do.py')
f = open(os.path.split(os.path.realpath(__file__))[0] + '/actions/' + argv[1] + '.py', 'r')
# 这里之所以用exec是为了防止出现python环境问题,甚至可以暴力的用os.popen()执行'do.py'
exec(f.read()) #exec('文件名称与命令相对应')
elif argv[1] == '-h' or argv[1] == '--help':
pring('help message')
else:
exit()
action/dothing.py
"""program dothing
Usage:
program dothing [flags... | -h]
Options:
-h --help Show this screen.
flags... flags...
"""
from docopt import docopt
if __name__ == '__main__':
arguments = docopt(__doc__, sys.argv[1:])
if arguments['--help']:
print('help message')
else:
flags = arguments['flags...']
# deal program dothing flags....
action/do.py
# 类似cli.py继续向下传递
action/do/model1.py (action.do.model1.py也可以,这个也是规范问题,只有寻找路径的方式能找到对应文件即可)
# 类似action/dothing.py处理
Reproduced please indicate the author and the source, and error a link to this page.
text link: //sealbaby.cn/cli-tool-experience