比较Python命令行解析库 — Argparse、Docopt与Click(2)

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

错误处理

错误处理是任何应用程序的重要组成部分。本节将探讨每个应用程序的默认错误处理,并在需要时实现附加逻辑。我们将探讨三个错误情况:

  1. 参数不足。

  2. 无效的选项/标志。

  3. 需要标志给一个值。

Argparse

39.png

argparse处理所有的错误情况非常好。

Docopt

40.png

遗憾地是,即使让docopt到可接受的最低错误处理水平,我们仍要做一点工作。docopt中推荐的验证方法是schema模块。*确保安装 – pip install schema。此外,他们提供了一个非常基础的验证例子。以下是我们带schema验证的应用程序:

41.png

有了这个验证,我们现在得到一些错误信息。

42.png

虽然这些信息描述性不强,并且可能对于大型应用程序来说很难调试,但总比没有验证好。schema模块确实提供了添加更多描述错误信息的其它机制,但这里我们不涉及这些。

Click

43.png

像argparse,click默认处理错误输入。

--------------------------------------------------------------------------------

我们已经完成了我们要建立的命令行应用程序的构造。在结束之前,让我们看看另一个可能的方案。

Invoke

我们可以使用一个简单的任务运行库invoke来创建问候命令行应用程序吗?

让我们从greeter的最简单版本开始:

tasks.py

44.png

从这个非常简单的文件中,我们得到一两个任务和非常小的帮助。从tasks.py的同一个目录下,我们得到以下结果:

45.png

现在,添加选项/标志 – --greeting和--caps。此外,我们可以把greeting逻辑放进它自己的函数,就像我们在其它工具所做的一样。

46.png

现在,我们事实上有一个在开始时指定的完整的接口!

47.png

帮助文档

为了argparse, docopt, 与click竞争,我们还需要增加完整的帮助文档。幸运的是,这也是可用的,通过使用invoke中装饰器@task的help参数和增加装饰函数的docstrings。

48.png

49.png

版本选项

实现--version选项不是那么简单。我们将添加version=False作为每个任务的选项,那么如果是True调用新的print_version函数。为了使这可行,我们要默认任何位置参数否则报错:

50.png

也要注意,我们在hello和goodbye命令调用--version,因为invoke本身有版本命令:

51.png

完整的版本命令的实现如下:

52.png

现在我们可以问invoke工具的版本:

53.png

结论

回顾一下,让我们看看我们创建的每个工具的最终版本。

Argparse

54.png

Docopt

55-1.png

55-2.png

Click

56-1.png

56-2.png

Invoke

57-1.png

57-2.png

我的推荐

现在,为了解决这个问题,我个人喜欢的库是click。去年,我一直在大型、多命令、复杂接口中使用它(感谢@kwbeam将click介绍给我)。我喜欢装饰方法,并认为它有一个非常干净的,可组合的接口。话虽如此,让我们公平地评价每个库。

arparse

Arparse是标准库(包括Python)用于创建命令行工具。仅凭这一事实,它可以说是这里最常用的审查工具。Argparse也很容易使用,因为很多魔术(隐式工作发生在幕后)用于构造接口。例如,参数和选项都是使用add_arguments函数定义,并且argparse指出幕后哪个是哪个。

docopt

如果你认为编写文档是主要的,docopt适合你!此外,docopt已经有许多其它语言的实现 –意思是你可以学习一个库,并跨语言使用它。docopt的缺点是,你必须以非常结构化的方式定义你的命令行结构。(有人会说这是件好事!)

click

我已经说过我真的很喜欢click,并且已经在生产中使用了一年多。我鼓励你读完整的为什么使用Click?文档。事实上,该文档启发了这个博客帖子!click装饰器风格的实现用起来很简单,并且因为你正在装饰想要执行的函数,它使得阅读代码很容易并弄清楚将执行什么。此外,click支持高级特性如回调, 命令嵌套等等。Click基于过时的optparse库的一个fork。

invoke

此比较中,Invoke 惊到我。我想一个设计用来任务执行的库不可以轻松地匹配完整的命令行库-但invoke库可以!话虽如此,我不建议它用于这种类型的工作,因为你一定会遇到的限制比这里提出的例子更复杂。

额外:包装

由于并不是每个人都使用setuptools(或其它解决方案)打包python源代码,我们决定文章的核心组成部分不包括这。此外,我们不想packaging成为完整的主题。如果你想学习更多关于使用setuptools打包去这里或者使用conda打包去这里或者你可以阅读我之前关于conda打包的博客帖子。我们这里涉及的是如何使用entry_points选项让命令行应用程序安装时可执行。

入口点

entry_point本质上是一个到代码单一函数的映射,系统PATH将给出一个命令。entry_point的形式是command = package.module:function

解释这的最好方式是查看click示例并添加一个入口点。

包装Click命令

Click使包装简单,默认情况下,当我们执行程序时,调用一个函数:

58.png

除了剩余的setup.py(此处不涉及),我们将添加以下来为我们的click应用程序创建entry_point。

假定如下目录结构-

59.png

我们将创建以下entry_point:

60.png

当用户安装entry_point创建的包时,setuptools将创建以下可执行脚本(调用greet)并放置它在用户系统的PATH。

61.png

安装后,用户可以运行以下内容:

62.png

包装Argparse命令

我们需要做的唯一与click不同的是将应用程序初始化写到一个单独的函数中,这样我们可以在entry_point调用。

代码:

63.png

变成:

64.png

针对entry_point,现在我们可以使用click中定义的相同的模式。

包装Docopt命令

打包docopt命令和打包argparse命令的过程相同。

代码:

65.png

变成:

66.png

英文原文:https://realpython.com/blog/python/comparing-python-command-line-parsing-libraries-argparse-docopt-click/
译者:小雨