当你想实现一个命令行程序时,或许第一个想到的是用 Python 来实现。比如 CentOS 上大名鼎鼎的包管理工具 yum 就是基于 Python 实现的。
而 Python 的世界中有很多命令行库,每个库都各具特色。但我们往往不知道其背后的设计理念,也因此在选择时感到迷茫。这些库的作者为何在重复造轮子,他是从哪个角度来考虑,来让命令行库“演变”到一个新的更好用的形态。
为了能够更加直观地感受到命令行库的设计理念,在此之前,我们不妨设计一个名为 calc 的命令行程序,它能:
支持 echo 子命令,对输入的字符串做处理来输出
若不提供任何选项,则输出原始内容
若提供 --lower 选项,则输出小写字符串
若提供 --upper 选项,则输出大写字符串
支持 eval 子命令,针对输入调用 Python 的 eval 函数,将结果输出(作为示例,我们不考虑安全性问题)
argparse
argparse 作为 Python 的标准库,可能会是你想到第一个命令行库。
argparse 的设计理念就是提供给开发者最细粒度的控制。换句话说,你需要告诉它必不可少的细节,比如参数的类型是什么,处理参数的动作是怎样的。
在 argparse 的世界中,需要:
设置解析器,作为后续定义参数和解析命令行的基础。如果要实现子命令,则还要设置子解析器。
定义参数,包括名称、类型、动作、帮助等。其中的动作是指对于此参数的初步处理,是直接存下来,还是作为布尔值,亦或是追加到列表中等等
解析参数
根据参数编写业务逻辑
以下示例是基于 argparse 的 calc 程序:
import argparse
def echo_text(args):
if args.lower:
print(args.text.lower())
elif args.upper:
print(args.text.upper())
else:
print(args.text)
def eval_expression(args):
print(eval(args.expression))
1. 设置解析器
parser = argparse.ArgumentParser(description=‘Calculator Program.’)
subparsers = parser.add_subparsers()
2. 定义参数
2.1 echo 子命令
echo 子解析器
echo_parser = subparsers.add_parser(
‘echo’, help=‘Echo input text in multiple forms’)
添加位置参数 text
echo_parser.add_argument(‘text’, help=‘Input text’)
–lower/–upper 互斥,需要设置互斥组
echo_group = echo_parser.add_mutually_exclusive_group()
添加选项参数 --lower/–upper,这里action的作用就是将之变为布尔变量
echo_parser.add_argument(’–lower’, action=‘store_true’, help=‘Lower input text’)
echo_parser.add_argument(’–upper’, action=‘store_true’, help=‘Upper input text’)