让你如“老”绅士般编写 Python 命令行工具的开源项目:docopt

2023-11-25 20:50

本文主要是介绍让你如“老”绅士般编写 Python 命令行工具的开源项目:docopt,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

640?wx_fmt=jpeg

作者:HelloGitHub-Prodesire

文中涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库[1]

点击本文最下方的“阅读原文”即可获取

一、前言

在第一篇“初探 docopt”的文章中,我们初步掌握了使用 docopt 的三个步骤,了解了它不同于 argparse 的设计思路。那么 docopt 的使用模式都有哪些呢?其接口描述中都支持哪些语法规则呢?本文将带你深入了解 docopt

本系列文章默认使用 Python 3 作为解释器进行讲解。	
若你仍在使用 Python 2,请注意两者之间语法和库的使用差异哦~

二、使用模式

在上一篇文章中我们提到 docopt 是通过定义一个包含特定内容的字符串,也就是接口描述,来达到描述命令行功能的目的。那么接口描述的总体规则是这样的:

  • 位于关键字 usage:(大小写不敏感)和一个可见的空行之间的文本内容会被解释为一个个使用模式。
  • useage: 后的第一个词会被解释为程序的名称,比如下面就是一个没有命令行参数的示例程序:
Usage: cli
  • 接口描述中可以包含很多有各种元素的模式,以描述命令行用法,比如:
Usage:	cli command --option <argument>	cli [<optional-argument>]	cli --another-option=<with-argument>	cli (--either-that-option | <or-this-argument>)	cli <repeating-argument> <repeating-argument>...

2.1 位置参数:

使用 <> 包裹的参数会被解释为位置参数。

比如,我们可以指定两个位置参数 xy ,先添加的 x 位于第一个位置,后加入的 y 位于第二个位置。那么在命令行中输入 1 2的时候,分别对应到的就是 xy

"""	
Usage: cli <x> <y>	
"""	
from docopt import docopt	arguments = docopt(__doc__, argv=['1', '2'])	
print(arguments)

其输出为:

{'<x>': '1',	'<y>': '2'}

2.2 选项参数:-o --option

以单个破折号(-)开头的的参数为短选项,以双破折号(--)开头的参数为长选项。

  • 短选项支持集中表达多个短选项,比如 -abc 等价于 -a-b-c
  • 长选项后可跟参数,通过 空格= 指定,比如 --input ARG 等价于 --input=ARG
  • 短选项后可跟参数,通可选的 空格 指定,比如 -f FILE 等价于 -fFILE

在下面这个例子中,我们希望通过 -n h 或 --name 来指定名字:

"""	
Usage:	cli [options]	Options:	-n, --name NAME   Set name.	
"""	
from docopt import docopt	arguments = docopt(__doc__, argv=['-n', 'Eric'])	
print(arguments)	arguments = docopt(__doc__, argv=['-nEric'])	
print(arguments)	arguments = docopt(__doc__, argv=['--name', 'Eric'])	
print(arguments)	arguments = docopt(__doc__, argv=['--name=Eric'])	
print(arguments)

上面的示例中,我们通过 4 种方式(2 个短选项参数方式和 2 个长选项参数方式)来指定命令行输入,其输出均为:

{'--name': 'Eric'}

需要注意的是:

--input ARG(而不是 --input=ARG)的含义是模糊不清的,因为这不能看出 ARG 究竟是选项参数, 还是位置参数。在 docopt 的使用模式中,只有在接口描述中定义了对应选项才会被解释为一个带参数的选项, 否则就会被解释为一个选项和一个独立的位置参数。

-f FILE-fFILE 这种写法也有同样的模糊点。后者无法说明这究竟是一系列短选项的集合, 还是一个带参数的选项。只有在接口描述中定义了对应选项才会被解释为一个带参数的选项。

2.3 命令

这里的命令也就是 argparse 中嵌套解析器所要完成的事情,准确的说,对整个命令行程序来说,实现的是子命令。

docopt 中,凡是不符合 --options<arguments> 约定的词,均会被解释为子命令。

在下面这个例子中,我们支持 createdelete 两个子命令,用来创建或删除指定路径。而 delete 命令支持 --recursive 参数来表明是否递归删除指定路径:

"""	
Usage:	cli create	cli delete [--recursive]	Options:	-r, --recursive   Recursively remove the directory.	
"""	
from docopt import docopt	arguments = docopt(__doc__)	
print(arguments)

直接指定 delete -r,输出如下:

$ python3 cli.py delete -r	{'--recursive': True,	'create': False,	'delete': True}

2.4 可选元素:[optional elements]

以中括号“[]”包裹的元素(选项、参数和命令)均会被标记为可选。多个元素放在一对中括号中或各自放在中括号中是等价的。比如:

Usage: cli [command --option <argument>]

等价于:

Usage: cli [command] [--option] [<argument>]

2.5 必填元素:(required elements)

没被中括号“[]”包裹的所有元素默认都是必填的。但有时候使用小括号“()”将元素包裹住,用以标记必填是有必要的。比如,要将多个互斥元素进行分组:

Usage: my_program (--either-this <and-that> | <or-this>)

另一个例子是,当出现一个参数时,也要求提供另一个参数,那么就可以这么写:

Usage: my_program [(<one-argument> <another-argument>)]

这个例子中 <one-argument><another-argument> 要么都出现,要么都不出现。

2.6 互斥参数:element|another

argparse 中要想实现互斥参数,还需要先调用 parser.add_mutually_exclusive_group() 添加互斥组, 再在组里添加参数。而在 docopt 中就特别简单,直接使用 | 进行分隔:

Usage: my_program go (--up | --down | --left | --right)

在上面的示例中,使用小括号“()”来对四个互斥选项分组,要求必填其中一个选项。在下面的示例中,使用中括号“()”来对四个互斥选项分组,可以不填,或填其中一个选项:

Usage: my_program go [--up | --down | --left | --right]

我们还可以发散一下思路,子命令天然需要互斥,那么除了这种写法:

Usage: my_program run [--fast]	my_program jump [--high]

使用如下 | 的写法,也是等价的:

Usage: my_program (run [--fast] | jump [--high])

2.7 可变参数列表:element...

可变参数列表也就是定义参数可以有多个值。在 argparse 中,我们通过 parser.add_argument('--foo', nargs='?') 来指定,其中 nargs 可以是数字、?+*来表示参数个数。

docopt 中,自然也有相同的能力,使用省略号 ... 来实现:

Usage: my_program open <file>...	my_program move (<from> <to>)...

若要参数提供 N 个,则写 N 个参数即可,比如下面的示例中要求提供 2 个:

Usage: my_program <file> <file>

若要参数提供 0 个或多个,则配合中括号“[]”进行定义,如下 3 中定义方式等价:

Usage: my_program [<file>...]	my_program [<file>]...	my_program [<file> [<file> ...]]

若要参数提供 1 个或多个,则可以这么写:

Usage: my_program <file>...

在下面完整示例中,所获得的 arguments{'<file>': ['f1', 'f2']}

"""	
Usage:	cli <file>...	
"""	
from docopt import docopt	arguments = docopt(__doc__, argv=['f1', 'f2'])	
print(arguments)	

2.8 选项简写:[options]

“[options]”用于简写选项,比如下面的示例中定义了 3 个选项:

Usage: my_program [--all --long --human-readable] <path>	--all             List everything.	
--long            Long output.	
--human-readable  Display in human-readable format.

可以简写为:

Usage: my_program [options] <path>	--all             List everything.	
--long            Long output.	
--human-readable  Display in human-readable format.

如果一个模式中有多个选项,那么这会很有用。

另外,如果选项包含长短选项,那么也可以用它们中的任意一个写在模式中,比如下面的示例的模式中均使用短选项:

Usage: my_program [-alh] <path>	-a, --all             List everything.	
-l, --long            Long output.	
-h, --human-readable  Display in human-readable format.

2.9 [--]

当双破折号“--”不是选项时,通常用于分隔选项和位置参数,以便处理例如将文件名误认为选项的情况。为了支持此约定,需要在位置参数前添加 [--]

Usage: my_program [options] [--] <file>...

2.10 [-]

当单破折号“-”不是选项时,通常用于表示程序应处理 stdin,而非文件。为了支持此约定,需要在使用模式中加入 [-]

2.11 选项描述

选项描述就是描述一系列选项参数的模式。如果使用模式中的选项定义是清晰的,那么选项描述就是可选的。

选项描述可以定义如下内容:

  • 短选项和长选项代表相同含义
  • 带参数的选项
  • 有默认值的选项参数

选项描述的每一行需要以 --- 开头(不算空格),比如:

Options:	--verbose   # 好	-o FILE     # 好	
Other: --bad  # 坏, 没有以 "-" 开头

选项描述中,使用空格或“=”来连接选项和参数,以定义带选项的参数。参数可以使用 <Arg> 的形式, 或是使用 ARG 大写字母的形式。可用逗号“,”来分隔长短选项。比如:

-o FILE --output=FILE       # 没有逗号 长选项使用 "=" 分隔	
-i <file>, --input <file>   # 有逗号, 长选项使用空格分隔

选项描述中每个选项定义和说明之间要有两个空格,比如:

--verbose MORE text.    # 坏, 会被认为是带参数 MORE 的选项	# --version 和 MORE text. 之间应该有2个空格	
-q        Quit.         # 好	
-o FILE   Output file.  # 好	
--stdout  Use stdout.   # 好,2个空格

选项描述中在说明中使用 [default: <default-value>] 来给带参数的选项赋以默认值,比如:

--coefficient=K  The K coefficient [default: 2.95]	
--output=FILE    Output file [default: test.txt]	
--directory=DIR  Some directory [default: ./]

三、小结

关于 docopt 的方方面面我们都了解的差不多了,回过头来看。对于命令行元信息的定义,它比 argparse 要来的更加简洁。

argparse 像是命令式编程,调用一个个的函数逐步将命令行元信息定义清楚;而 docopt 则像是声明式编程,通过声明定义命令行元信息。

两者站在的维度不同,编程的套路也不尽相同,甚是有趣。

了解了这么多,也该练练手了。在下篇文章中,我们仍然会以 git 命令作为实战项目,看看如何使用 docopt 来实现 git 命令。

参考资料

[1]HelloGitHub-Team 仓库: https://github.com/HelloGitHub-Team/Article

640?wx_fmt=png

关注公众号加入交流群,一起讨论有趣的技术话题

『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎联系我(微信:xueweihan,备注:讲解)加入我们,让更多人爱上开源、贡献开源~

“阅读原文”获取更多信息、“在看”让本文被更多人看到、“赞赏”支持我们。

Python 命令行之旅 往期回顾:


这篇关于让你如“老”绅士般编写 Python 命令行工具的开源项目:docopt的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/424596

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定

金融业开源技术 术语

金融业开源技术  术语 1  范围 本文件界定了金融业开源技术的常用术语。 本文件适用于金融业中涉及开源技术的相关标准及规范性文件制定和信息沟通等活动。

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学