用Click编写Python命令行工具

2018 年 1 月 29 日 Python程序员

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

在编写Python命令行(CLI)应用程序时,使用Click库进行参数解析的深入教程

Python通常被称为胶水语言,因为它非常灵活,并且能够与现有的程序很好地联结在一起。 这意味着很大一部分Python代码被编写为脚本和命令行界面(CLI)。

构建这些命令行界面和工具是非常强大的,因为它使得几乎所有的东西都可以自动化。 因此,随着时间的推移,CLI可能变得相当复杂。

通常从一个非常简单的脚本开始,运行这些python代码来完成一件特定的事情。例如:访问web API并将输出打印到控制台:

仅通过python print_user_agent.py你就可以运行它,它就会打印出 API调用的user-agent。

正如我所说,一个非常简单的脚本。


但是,当这样一个Python命令行脚本变得越来越复杂时,你有什么选择?

这就是我们将在整个教程中看到的内容。您将学习关于Python中构建CLI的基本知识,以及Click如何使其成为更好的体验。

我们将使用这些知识,并从简单的脚本一步一步地通过命令行参数、选项及有用的用法说明CLI。所有这些都使用了一个叫做click的框架。

在本教程的最后,你会知道:

  • 为什么click相比于argparse和optparse来说是一个更好的选择

  • 如何用它创建一个简单的CLI

  • 如何将强制命令行参数添加到您的脚本

  • 如何解析命令行标志和选项

  • 如何通过添加帮助(使用)文本,使命令行应用程序更加便于用户使用。

而且你也会看到如何用最少量的代码来实现所有的功能。

顺便说一下,本教程中的所有代码示例都使用Python 3.6。它们可能不适用于Python的早期版本,但是如果遇到任何麻烦,请在下面留言,我们将把它整理在一起。

让我们开始吧!

为什么要编写Python命令行脚本和工具?

上面的代码片段仅仅是一个例子,在现实生活中并不是很有用。我在Python开发人员的职业生涯中编写的脚本要复杂得多。它们通常帮助构建,测试和部署应用程序,并使流程可重复。

您可能有自己的经验,并知道这可能是我们日常工作的一大部分:有些脚本仍然保留在你们所构建的项目中,有些对其他团队或项目都有用,甚至可以扩展更多的功能。

在这些情况下,使脚本更加灵活或者可以使用命令行参数进行配置变得非常重要。它使得向脚本提供服务器名称,凭证或任何其他信息成为可能。

这就是像optparse和argparse这样的Python模块,让你的生活变得更轻松。但是,在我们仔细研究这些之前,让我们直接说一下我们的术语。


命令行接口的基础知识

命令行界面(CLI)以可执行文件的名称开头。您可以在控制台中键入它的名称,并访问脚本的主要入口点,例如pip。

根据CLI的复杂性,通常可以将参数传递给脚本,可以是:

1.参数,它是传递给脚本的必需参数。如果您不提供它,CLI将返回一个错误。例如,click是这个命令中的参数:pip install click。

2.或者它可以是一个选项,它是一个可选的(||)参数,结合名称和值部分,如--cache-dir ./my-cache。你告诉CLI应将./my-cache值用作缓存目录。

3.一个特殊选项是启用或禁用特定行为的标志。最常见的可能是 --help。您只需指定名称,CLI将在内部解释该值

使用更复杂的CLI(例如pip或Heroku Toolbelt),您可以访问集合入口的功能。它们通常被称为命令子命令

当你使用pip install <PACKAGE NAME>安装Python包时,您可能已经使用了CLI。命令install会告诉CLI您将访问该功能来安装软件包,并使你能访问该特性的参数。


Python 3.x标准库中提供的命令行框架

将命令和参数添加到脚本中是非常强大的,但命令行的解析并不像您想象的那样直截了当。 你应该使用已经解决了这个问题的Python的软件包之一,来替代你自己写。

两个最着名的软件包是optparse和argparse。 它们是遵循“包含电池”原则的Python标准库的一部分。

他们大多提供相同的功能且使用代码非常相似。 最大的不同在于,optparse自Python 3.2以来已被弃用,argparse被认为是在Python中实现CLI的标准

你可以在Python文档中找到更多关于它们的详细信息,来让你知道一个argparse脚本是什么样子的,下面是一个例子:


click vs argparse:一个更好的选择?

你可能正在看上面的代码示例,在想“这些东西是什么意思?”这正是我在使用argparse遇到的一个问题:它不直观,很难阅读。

这就是为什么我爱上了click

click正在解决与optparse和argparse相同的问题,但使用方法稍微不同。它使用装饰器的概念。这需要命令是可以使用装饰器包装的函数。

丹写了一个很好的介绍,如果这是你第一次听到这个词,或许你想快速学习。

作者Armin Ronacher详细描述了他为什么写这个框架。您可以阅读文档中的“Why Click?”部分,我鼓励您看一下。

我使用click的主要原因是你可以使用少量代码轻松构建功能丰富的CLI。即使您的CLI增长并且变得更加复杂,代码也很容易阅读。


通过Click构建一个简单的Python命令行界面

我已经谈了很多CLI和框架。我们来看看用click来构建一个简单的CLI是什么意思。与本教程中的第一个示例类似,我们可以创建一个简单的基于click的CLI,它向控制台打印一些东西。这并不是很费力:


首先,我们现在不用担心最后两行,当文件作为脚本执行时,这只是Python(稍微不直观)的方式来运行主函数。

正如你所看到的,我们所要做的就是创建一个函数并添加@ click.command()装饰器。 这将它变成一个click命令,这是我们的脚本的主要入口点。 你现在可以在命令行上运行它,你会看到类似这样的东西:

click 之所以比较美观是因为,我们免费获得一些额外的功能。 我们没有实现任何帮助功能,但添加了--help选项,您将看到一个打印到命令行的基本帮助页面:


Click更实际的PythonCLI示例

现在你已经知道click是如何使得建立一个简单的CLI更容易了,我们将看一个稍微更现实的例子。我们将构建一个允许我们与Web API 进行交互的程序。最近每个人都会使用,它们让我们访问一些更酷的数据。

本教程其余部分将介绍的API是OpenWeatherMap API。 它提供当前天气以及特定位置的五天预报。 我们将从他们的API示例返回当前天气的位置。

在开始编写代码之前,我喜欢尝试使用API来更好地理解它是如何工作的。 我想你应该知道的一个工具是HTTPie,我们可以使用它来调用示例API并查看返回的结果。 你甚至可以尝试他们的在线终端来运行它,无需安装。

让我们来看看当我们将API中的位置设置为london时会发生什么:

如果你正在用这样的面孔查看屏幕😱因为上面的例子包含一个API密钥,所以不要担心这是他们提供的示例API密钥。

上面例子中比较重要的一点是,我们发送两个查询参数(使用HTTPie时用==表示)来获取当前天气:

  • q是我们的地点名称; 

  • appid是我们的API密钥。

这使我们可以使用Python和Requests库创建一个简单的实现(为简单起见,我们将忽略错误处理和失败请求)。

这个函数使用两个查询参数向天气API发出一个简单的请求。 它需要一个强制的参数location,它被假定为一个字符串。 我们还可以通过在函数调用中传递api_key来提供API密钥。  它是可选的,可以使用示例键作为默认值。

这里是我们目前伦敦的天气,形成Python REPL:



click 解析一个必选参数

简单的current_weather函数允许我们使用用户提供的自定义位置来构建我们的CLI。 我希望它能像这样工作:

你可能已经猜到了,这次调用的位置就是我之前介绍的一个参数。 这是因为它是我们天气CLI的强制性参数。

我们如何在Click中实现? 这很简单,我们使用一个名为参数的装饰器。 谁会想到?

我们先来看一个简单的例子,通过定义参数的位置来修改它。


你可以看到,我们所要做的就是添加一个额外的装饰器到我们的主要功能,并给它一个名字。Click使用该名称作为变量传递到包装函数的参数中。

在我们的例子中,命令行参数location的值将作为位置参数传递给主函数。有道理吧?

你也可以在你的名字中使用破折号( - ),例如api-key,在这个函数中,Click会将名字的中划线变为下划线。例如main(api_key)。

main的实现只需使用我们的current_weather函数来获取CLI调用者提供的位置的天气。 然后我们使用一个简单的打印语句输出天气信息||

完成!

如果这个打印语句对你来说看起来很奇怪,那是因为这是一种用Python 3.6+格式化字符串的新方法,称为f-string格式。 你应该查看 “Python中进行字符串格式化的4种主要方法”来了解更多。


cllick 解析可选参数

你可能已经找到了我们上面使用的示例API的一个小小的缺陷,你是一个聪明人

是的,这是一个静态的端点,从2017年1月起总是返回伦敦的天气。所以让我们用一个真实的API密钥来请求实际的API。

我们需要改变的第一件事是当前天气的URL端点。 我们可以通过在OpenWeatherMap文档中将current_weather函数中的url替换为端点来实现:

我们刚刚做出的更改将会破坏我们的CLI,因为默认API密钥对真实API无效。 该API将返回一个401 UNAUTHORIZED HTTP状态码。 不相信我? 这是证明:

所以让我们添加一个新的参数给我们的CLI,允许我们指定API密钥。 但首先,我们必须决定这应该是一个参数还是一个选项。

我们使它成为一个option,因为添加一个像--api-key这样的命名参数使得它更加明确和自描述。

以下是我认为用户应该运行它的方式:

很好很容易。 所以让我们看看我们如何将它添加到我们现有的click命令。

再来一次,我们正在为我们的main函数添加一个装饰器。 这一次,我们使用非常直观的命名@ click.option,并添加了我们的option名称,包括前双破折号( -- )。 正如你所看到的,我们也可以用一个短划线( - )来提供一个快捷方式来保存用户的一些输入。

我之前提到,click从较长的版本创建传递给主函数的参数。 在option的情况下,它将划破前面的破折号并将其变成snake_case的情况。 --api-key变成api_key。

我们必须做的最后一件事是将API密钥传递给我们的current_weather函数。

我们使CLI用户可以使用自己的密钥并查看任何位置:

看着我的窗口,我可以证实这是真的。


将自动生成的使用说明添加到您的Python命令行工具中

你可以安慰自己,你已经用最少量的Boilerplate_code构建了一个很棒的小CLI。但是在你休息或者享受一杯饮料之前, 通过添加一些文档,让我们确保一个新的用户能够知道如何运行我们的小CLI ...(不要跑,超级简单的。)

首先让我们来看看在我们做了所有更改之后,--help标志将会显示什么。 正如你所看到的,所有努力都不是白费力的:

我们想要解决的第一件事是我们的API密钥选项丢失的描述。 我们所要做的就是向@click.option装饰器提供一个帮助文本:

我们要做的第二个也是最后一个更改是添加整个click命令的文档。 而最简单的方式就是添加一个文档字符串到我们的main函数。 是的,我们应该这样做,所以这不是额外的工作:

综合起来,我们的天气工具得到了非常好的输出。

我希望在这一点上,你感觉到了当我第一次发现click时的感觉:


带有click的Python CLI:摘要&回顾

好的,我们已经在本教程中介绍了大量的内容。 现在是您为自己感到自豪的时候了。 以下是你所学到的:

  • 为什么click是一个更好的选择相对argparse和optparse

  • 如何用它创建一个简单的CLI

  • 如何将强制命令行参数添加到您的脚本

  • 如何解析命令行标志和选项;

  • 如何通过添加帮助(使用)文本使您的命令行应用程序更加用户友好

而所有这些都是用最少量的引用! 下面的完整代码示例说明了这一点。你可以自由地使用它来做你自己的实验

如果这启发了你,你应该看看click官方文档以获得更多的功能。 您也可以查看我在2016 PyCon US 关于click的介绍。或者留意我的后续教程,您将在其中学习如何为我们的天气CLI添加更多高级功能。

开心的CLI编码!


英文原文:https://dbader.org/blog/python-commandline-tools-with-click#intro
译者:韩晓


登录查看更多
2

相关内容

Python是一种面向对象的解释型计算机程序设计语言,在设计中注重代码的可读性,同时也是一种功能强大的通用型语言。
【实用书】Python技术手册,第三版767页pdf
专知会员服务
235+阅读 · 2020年5月21日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
180+阅读 · 2020年1月1日
Python奇淫技巧,5个数据可视化工具
机器学习算法与Python学习
7+阅读 · 2019年4月12日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
Python用法速查网站
Python程序员
17+阅读 · 2018年12月16日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
在浏览器中使用tensorflow.js进行人脸识别的JavaScript API
人工智能头条
6+阅读 · 2018年7月2日
刚开始学编程?这几款小工具能让你事半功倍
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
Python为啥这么牛?
Python程序员
3+阅读 · 2018年3月30日
利用python操作Excel教程
Python技术博文
4+阅读 · 2017年9月13日
Rapid Customization for Event Extraction
Arxiv
7+阅读 · 2018年9月20日
Arxiv
23+阅读 · 2018年8月3日
Arxiv
14+阅读 · 2018年4月18日
Arxiv
9+阅读 · 2018年3月23日
Arxiv
5+阅读 · 2017年7月23日
VIP会员
相关资讯
Python奇淫技巧,5个数据可视化工具
机器学习算法与Python学习
7+阅读 · 2019年4月12日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
Python用法速查网站
Python程序员
17+阅读 · 2018年12月16日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
在浏览器中使用tensorflow.js进行人脸识别的JavaScript API
人工智能头条
6+阅读 · 2018年7月2日
刚开始学编程?这几款小工具能让你事半功倍
Python 杠上 Java、C/C++,赢面有几成?
CSDN
6+阅读 · 2018年4月12日
Python为啥这么牛?
Python程序员
3+阅读 · 2018年3月30日
利用python操作Excel教程
Python技术博文
4+阅读 · 2017年9月13日
Top
微信扫码咨询专知VIP会员