为程序编写command line interface总是一件麻烦的事,尤其是程序支持多个参数,参数之间还有关系的时候,就更为棘手了。当我在编写 mdtogh 这个工具时就遇到这个问题。
好在,python的优点之一就是第三方的模块特别多,而今天就要介绍用来解决这个问题的强大模块:
不是python用户?别急,docopt也port到其他语言上了,在文章最后有所介绍。先把介绍看完吧。
docopt
docopt是一个第三方开发的模块,用于创建command line interface。其完成的工作很简单:
- 处理命令行参数
其在PyCon UK 2012被介绍,您可以在youtube上看到相应的介绍。
特性
- 从字符串中生成相应参数
- 支持多种格式
- 可选参数
- 命令
- 特定位置的参数
- 自动生成帮助命令
- 参数可以设定默认值
- 及其他特性
一个简单的例子
exam.py
import sys from docopt import docopt doc=''' Usage: my_program tcp <host> <port> [--timeout=<seconds>] my_program serial <port> [--baud=<n>] [--timeout=<seconds>] my_program (-h | --help | --version) Options: -h, --help Show this screen and exit. --baud=<n> Baudrate [default: 9600] --timeout=<seconds> timeout [default: 50] '''def test(argv=None):if argv isNone: argv = sys.argv[1:] args = docopt(doc, argv=argv, version='0.01')print args passif __name__ =='__main__': test()
运行结果:
summertekiMacBook-Pro:docopt summer$ python exam.py Usage: my_program tcp <host><port>[--timeout=<seconds>] my_program serial <port>[--baud=<n>][--timeout=<seconds>] my_program (-h |--help |--version)
帮助输出:
summertekiMacBook-Pro:docopt summer$ python exam.py -h Usage: my_program tcp <host> <port> [--timeout=<seconds>] my_program serial <port> [--baud=<n>] [--timeout=<seconds>] my_program (-h | --help | --version) Options: -h, --help Show this screen and exit. --baud=<n> Baudrate [default: 9600] --timeout=<seconds> timeout [default: 50]
正确的输入:
summertekiMacBook-Pro:docopt summer$ python exam.py tcp 127.0.0.1 80 {'--baud': '9600', '--help': False, '--timeout': '50', '--version': False, '<host>': '127.0.0.1', '<port>': '80', 'serial': False, 'tcp': True}
看到上面的程序及执行的结果,我们可以看到docopt已经很方便的帮我们创建了command line interface,并且是五脏俱全,几乎常用的cli写法都支持,很是方便。仅仅编写一个帮助文档,就能创建cli,的确轻松了不少。
安装
Python
库的安装方式是我觉得最方便,也是最优雅的安装方法了。仅仅一个语句就搞定:
pip install docopt
That’s it!剩下的就全部交给pip来解决了。
详细介绍
通过上面简单的例子,可以看到docopt
在实现command-line interface特别简单。
API
docopt仅仅提供了一个api
。就是我们上面用的docopt
。 查看其介绍,可以看到详细的介绍。
from docopt import docopt docopt(doc, argv=None, help=True, version=None, options_first=False)
doc
是必须的参数,而剩下的4个是可选的:
- doc:为可以被翻译的字符串。一般来说包含
Usage
及Options
两个字段.具体的介绍请参考下面。 - argv:可选的参数数组。docopt默认使用
sys.argv[1:]
,不过您也可以进行修改。 - help:docopt会把doc作为help手册提供给用户,您也可以设置为False,然后自己处理。
- version:当用户输入
--version
时显示该数据。其值可以为任何printable对象,一般是字符串。 - options_first: 禁止混合options及positional argument。在第一个positinal argument后,剩下的参数都会被认为是positional,即使长得像参数。您可以参考例子来了解其作用。
该方法返回包含用户输入参数的字典,命令及选项是字典的键,相对应的用户输入是相应的值。
Help Message格式
Help Message具有分成两部分:
- Usage
- Options
Usage
Usage字段以 Usage: 开头,以空行结尾,所以最简单的例子就是这样子的:
"""Usage: my_program.py """
Usage:后面的第一个字符会被替换成程序的名字。程序名后面接着就是参数等内容了,这又分为三种:
- 参数: 或者 ARGUMENT。注意,ARGUMENT是大写。
- 选项: –options 或者 -o. 选项需在
Options
字段中进行介绍。选项支持合并,例如-iov
会被分别解释为-o
,-i
,-v
.选项的参数可以是--f=FILE
,-f FILE
,-fFILE
- 命令
每个参数选项有以下格式:
- []:可选的元素,例如
my_program.py [-hvqo FILE]
- ():必要参数,所有不在
[]
里头的都是必要参数,所以my_program.py --path=<path> <file>
==my_program.py (--path=<path> <file>)
- |: 或操作,
()
包含的参数必选其一.例如(--clockwise|--counterwise)
,其中一个参数是必要的。[]
包含的参数只选其一且不是必要的.[--left|--right]
. - …: 表示还有更多参数。其返回的是一个数组.
Options
一般来说,options的内容包括:
- 同义的选项,例如
-v
与--verbose
- 有参数的选项
Options字段的要求:
- 字符串中以
-
或--
开始的行被解释为options的描述
Options: --verbose # GOOD -o FILE # GOOD Other: --bad # BAD, line does not start with dash "-"
- 对于有参数的字段,可以像下面展示的那样,以空格或
=
添加参数,相同意义的选项可以以空格或,
区分
-o FILE --output=FILE # without comma, with "=" sign -i <file>, --input <file> # with comma, without "=" sing
- 在参数的解释之前添加2个空格(这里一定要注意,不然会出问题)
--verbose More text. # BAD, will be treated as if verbose option had # an argument "More", so use 2 spaces instead -q Quit. # GOOD -o FILE Output file. # GOOD --stdout Use stdout. # GOOD, 2 spaces
- 对于需要默认参数的,可以添加
[default: <my-default-value>]
:
--coefficient=K The K coefficient [default: 2.95] --output=FILE Output file [default: test.txt] --directory=DIR Some directory [default: ./]
详细例子
docopt官方提供了很多样例以供学习参考,非常方便。
类似git支持子命令
为了支持子命令,必须要将 options_first
设置为True
。docopt提供了一个演示例子,创建了类似于git
的例子,具体请看该链接。
其他语言支持
docopt本身是一个python的库,不过有人已经移植到了其他语言中:
转载请注明:爱开源 » 为程序添加一个优雅的command line interface