python docopt_比较Python命令行解析库– Argparse,Docopt和Click

python docopt

About a year ago I began a job where building command-line applications was a common occurrence. At that time I had used argparse quite a bit and wanted to explore what other options were available. I found that the most popular alternatives available were click and docopt. During my exploration I also found that other than each libraries “why use me” section there was not much available for a complete comparison of the three libraries. Now there is – this blog post!

大约一年前,我开始从事构建命令行应用程序的工作。 当时我已经使用了argparse了很多,并想探索其他可用的选项。 我发现最受欢迎的替代方法是clickdocopt 。 在探索过程中,我还发现,除了每个库的“为什么使用我”部分外,没有太多可用于对三个库进行完整比较的内容。 现在有–此博客文章!

python command line tools

This is a guest blog post by Kyle Purdon​, an Application Engineer at Bitly in Denver.

这是由Denly in Denver的应用工程师Kyle Purdon 撰写的客座博客文章。

If you want to, you can head directly to the source though it really won’t do much good without the comparisons and step-by-step construction presented in this article.

如果愿意,可以直接使用源代码,但如果没有本文中介绍的比较和分步构建,它实际上并没有多大用处。

This article uses the following versions of the libraries:

本文使用以下版本的库:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13

命令行示例 (Command-Line Example)

The command-line application that we are creating will have the following interface:

我们正在创建的命令行应用程序将具有以下界面:

python [file].py [command] [options] NAME

python [file].py [command] [options] NAME

基本用法 (Basic Usage)

1
1
2
2
3
3
4
4
5
5

带选项的用法(标志) (Usage w/ Options (Flags))

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

This article will compare each libraries method for implementing the following features:

本文将比较用于实现以下功能的每种库方法:

  1. Commands (hello, goodbye)
  2. Arguments (name)
  3. Options/Flags (—greeting=<str>, —caps)
  1. 命令(你好,再见)
  2. 参数(名称)
  3. 选项/标志(-greeting = <str>,-caps)

Additional features:

附加功能:

  1. Version Printing (-v/--version)
  2. Automated Help Messages
  3. Error Handling
  1. 版本打印( -v/--version
  2. 自动帮助信息
  3. 错误处理

As you would expect argparse, docopt, and click implement all of these features (as any complete command-line library would). This fact means that the actual implementation of these features is what we will compare. Each library takes a very different approach that lends to a very interesting comparison – argparse=standard, docopt=docstrings, click=decorators.

如您所料,argparse,docopt并单击实现所有这些功能(就像任何完整的命令行库一样)。 这个事实意味着我们将比较这些功能的实际实现。 每个库采用的方法都非常不同,因此可以进行非常有趣的比较-argparse = standard,docopt = docstrings,click = decorators。

奖励部分 (Bonus Sections)

  1. I’ve been curious about using task-runner libraries like fabric and it’s python3 replacement invoke to create simple command-line interfaces, so I will try and put the same interface together with invoke.
  2. A few extra steps are needed when packaging command-line applications, so I’ll cover those steps as well!
  1. 我一直对使用像fabric这样的任务运行库感到好奇,它是通过python3替换调用来创建简单的命令行界面的,所以我将尝试将同一接口与invoke一起使用。
  2. 打包命令行应用程序时,需要一些额外的步骤,因此我也将介绍这些步骤!

指令 (Commands)

Let’s begin by setting up the basic skeleton (no arguments or options) for each library.

首先,为每个库设置基本框架(无参数或选项)。

精氨酸 (Argparse)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

With this we now have two commands (hello and goodbye) and a built-in help message. Notice that the help message changes when run as an option on the command hello.

有了这个,我们现在有了两个命令( hellogoodbye )和一个内置的帮助消息。 请注意,在命令hello上作为选项运行时,帮助消息会更改。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14

Docopt (Docopt)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14

With this we, again, have two commands (hello, goodbye) and a built-in help message. Notice that the help message DOES NOT change when run as an option on the hello command. In addition we do not need to explicitly specify the commands.py -h | --help in the Options section to get a help command. However, if we don’t they will not show up in the output help message as options.

有了这个,我们又有了两个命令( hellogoodbye )和一个内置的帮助消息。 请注意,作为hello命令的选项运行时,帮助消息不会更改。 此外,我们并不需要明确指定commands.py -h | --help Options部分中的commands.py -h | --help以获得帮助命令。 但是,如果不这样做,它们将不会作为选项显示在输出帮助消息中。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21

请点击 (Click)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19

With this we now have two commands (hello, goodbye) and a built-in help message. Notice that the help message changes when run as an option on the hello command.

有了这个,我们现在有了两个命令( hellogoodbye )和一个内置的帮助消息。 请注意,作为hello命令的选项运行时,帮助消息会更改。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15

Even at this point you can see that we have very different approaches to constructing a basic command-line application. Next let’s add the NAME argument, and the logic to ouput the result from each tool.

即使到了这一点,您也可以看到,我们使用不同的方法来构建基本的命令行应用程序。 接下来,我们添加NAME参数,以及从每个工具输出结果的逻辑。

争论 (Arguments)

In this section we will be adding new logic to the same code shown in the previous section. We’ll add comments to new lines stating their purpose. Arguments (aka positional arguments) are required inputs to a command-line application. In this case we are adding a required name argument so that the tool can greet a specific person.

在本节中,我们将为上一节中显示的相同代码添加新的逻辑。 我们将在新行中添加注释以说明其目的。 参数(aka位置参数)是命令行应用程序的必需输入。 在这种情况下,我们将添加必需的name参数,以便该工具可以问候特定的人。

精氨酸 (Argparse)

To add an argument to a subcommand we use the add_argument method. And in order to execute the correct logic, when a command is called, we use the set_defaults method to set a default function. Finally we execute the default function by calling args.func(args) after we parse the arguments at runtime.

要将参数添加到子命令,我们使用add_argument方法。 为了执行正确的逻辑,当调用命令时,我们使用set_defaults方法设置默认函数。 最后,我们在运行时解析参数后,通过调用args.func(args)执行默认功能。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

Docopt (Docopt)

In order to add an option, we add a <name> to the docstring. The <> are used to designate a positional argument. In order to execute the correct logic we must check if the command (treated as an argument) is True at runtime if arguments['hello']:, then call the correct function.

为了添加选项,我们在文档字符串中添加<name><>用于指定位置参数。 为了执行正确的逻辑,我们必须在运行时检查if arguments['hello']:True (视为参数),然后调用正确的函数。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13

Note that the help message is not specific to the subcommand, rather it is the entire docstring for the program.

请注意,帮助消息不是特定于子命令的,而是该程序的整个文档字符串。

请点击 (Click)

In order to add an argument to a click command we use the @click.argument decorator. In this case we are just passing the argument name, but there are many more options some of which we’ll use later. Since we are decorating the logic (function) with the argument we don’t need to do anything to set or make a call to the correct logic.

为了将参数添加到click命令,我们使用@click.argument装饰器。 在这种情况下,我们只是传递参数名称,但是还有更多选项 ,我们稍后将使用其中的一些选项 。 由于我们使用参数修饰逻辑(函数),因此无需执行任何操作即可设置或调用正确的逻辑。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8

标志/选项 (Flags/Options)

In this section we will again be adding new logic to the same code shown in the previous section. We’ll add comments to new lines stating there purpose. Options are non-required inputs that can be given to alter the execution of a command-line application. Flags are a boolean only (True/False) subset of options. For example: --foo=bar will pass bar as the value for the foo option and --baz (if defined as a flag) will pass the value of True is the option is given, or False if not.

在本节中,我们将再次为上一节中所示的相同代码添加新的逻辑。 我们将在新行中添加注释以表明目的。 选项是不需要的输入,可以提供这些输入来更改命令行应用程序的执行。 标志是选项的仅布尔值( True / False )子集。 例如:-- foo --foo=bar将传递bar作为foo选项的值,而--baz (如果定义为标志)将传递给定选项的True值,否则传递False

For this example we are going to add the --greeting=[greeting] option, and the --caps flag. The greeting option will have default values of Hello and Goodbye and allow the user to pass in a custom greeting. For example given --greeting=Wazzup the tool will respond with Wazzup, [name]!. The --caps flag will uppercase the entire response if given. For example given --caps the tool will respond with HELLO, [NAME]!.

对于本示例,我们将添加--greeting=[greeting]选项和--caps标志。 greeting选项将具有默认值HelloGoodbye并允许用户传递自定义问候语。 例如,给定--greeting=Wazzup该工具将以Wazzup, [name]!响应Wazzup, [name]! 。 如果给出--caps标志,则会将整个响应大写。 例如,给定--caps该工具将以HELLO, [NAME]!响应HELLO, [NAME]!

精氨酸 (Argparse)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19

Docopt (Docopt)

Once we hit the case of adding options with defaults, we hit a snag with the basic implementation of commands in docopt. Let’s continue just to illustrate the issue.

一旦遇到了使用默认值添加选项的情况,我们就对docopt中命令的基本实现产生了困扰。 让我们继续说明这个问题。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27

Now, see what happens when we run the following commands:

现在,看看运行以下命令会发生什么:

1
1
2
2
3
3
4
4
5
5

What?! Because we can only set a single default for the --greeting option both of our Hello and Goodbye commands now respond with Hello, Kyle!. In order for us to make this work we’ll need to follow the git example docopt provides. The refactored code is shown below:

什么?! 因为我们只能为--greeting选项设置一个默认值,所以我们的HelloGoodbye命令现在都以Hello, Kyle!响应Hello, Kyle! 。 为了使我们能够完成这项工作,我们需要遵循docopt提供的git示例 。 重构后的代码如下所示:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40
41
41
42
42
43
43
44
44
45
45
46
46
47
47
48
48
49
49
50
50
51
51
52
52
53
53
54
54
55
55
56
56
57
57
58
58
59
59
60
60
61
61
62
62
63
63
64
64
65
65
66
66
67
67
68
68
69
69

As you can see the hello|goodbye subcommands are now there own docstrings tied to the variables HELLO and GOODBYE. When the tool is executed it uses a new argument, command, to decide which to parse. Not only does this correct the problem we had with only one default, but we now have subcommand specific help messages as well.

如您所见, hello | goodbye子命令现在有自己的文档字符串,它们与变量HELLOGOODBYE 。 执行该工具时,它将使用新的参数command来决定要解析哪个参数。 这不仅可以解决只有一个默认设置的问题,而且现在还具有特定于子命令的帮助消息。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22

In addition all of our new options/flags are working as well:

另外,我们所有的新选项/标志也都在起作用:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8

请点击 (Click)

To add the greeting and caps options we use the @click.option decorator. Again, since we have default greetings now we have pulled the logic out into a single function (def greeter(**kwargs):).

要添加greetingcaps选项,我们使用@click.option装饰器。 同样,由于现在有了默认的问候语,我们已经将逻辑提取到一个函数中( def greeter(**kwargs):

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8

版本选项(—版本) (Version Option (—version))

In this section we’ll be showing how to add a --version argument to each of our tools. For simplicity we’ll just hardcode the version number to 1.0.0. Keep in mind that in a production application, you will want to pull this from the installed application. One way to achieve this is with this simple process:

在本节中,我们将展示如何在每个工具中添加--version参数。 为了简单起见,我们将版本号硬编码为1.0.0。 请记住,在生产应用程序中,您需要将其从已安装的应用程序中拉出。 实现此目的的一种方法是使用以下简单过程:

1
1
2
2
3
3
4
4

A second option for determining the version would be to have an automated version-bumping software change the version number defined in the file when a new version is released. This is possible with bumpversion. But this approach is not recommended as it’s easy to get out of sync. Generally, it’s best practice to keep a version number in as few places as possible.

确定版本的第二个选项是在发布新版本时,由自动版本转换软件更改文件中定义的版本号。 这是可能的bumpversion 。 但是不建议使用这种方法,因为它很容易脱离同步。 通常,最佳做法是将版本号保留在尽可能少的位置。

Since the implementation of adding a hard-coded version option is fairly simple we will use ... to denote skipped sections of the code from the last section.

由于添加硬编码版本选项的实现非常简单,因此我们将使用...表示最后一部分中跳过的代码部分。

精氨酸 (Argparse)

For argparse we again need to use the add_argument method, this time with the action='version' parameter and a value for version passed in. We apply this method to the root parser (instead of the hello or goodbye subparsers).

对于argparse,我们再次需要使用add_argument方法,这次使用action='version'参数和传入的version值。我们将此方法应用于根解析器(而不是hellogoodbye解析器)。

1
1
2
2
3
3
4
4
1
1
2
2

Docopt (Docopt)

In order to add --version to docopt we add it as an option to our primary docstring. In addition we add the version parameter to our first call to docopt (parsing the primary docstring).

为了将--version添加到docopt中,我们将其作为选项添加到主文档字符串中。 另外,我们在对docopt的第一次调用中添加了version参数(解析主docstring)。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
1
1
2
2

请点击 (Click)

Click provides us with a convenient @click.version_option decorator. To add this we decorate our greet function (main @click.group function).

Click为我们提供了一个方便的@click.version_option装饰器。 要添加此内容,我们装饰了greet函数(主@click.group函数)。

1
1
2
2
3
3
4
4
5
5
1
1
2
2

改善帮助(-h / —帮助) (Improving Help (-h/—help))

The final step to completing our application is to improve the help documentation for each of the tools. We’ll want to make sure that we can access help with both -h and --help and that each argument and option have some level of description.

完成我们的应用程序的最后一步是改善每个工具的帮助文档。 我们将要确保可以同时使用-h--help来访问帮助,并且每个参数和选项都具有一定程度的描述。

精氨酸 (Argparse)

By default argparse provides us with both -h and --help so we don’t need to add anything for that. However our current help documentation for the subcommands is lacking information on what --caps and --greeting do and what the name argument is.

默认情况下,argparse为我们提供-h--help因此我们不需要为此添加任何内容。 但是,我们当前有关子命令的帮助文档缺少有关--caps--greeting功能以及name参数是什么的信息。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

In order to add more information we use the help parameter of the add_argument method.

为了添加更多信息,我们使用add_argument方法的help参数。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14

Now when we provide the help flag we get a much more complete result:

现在,当我们提供帮助标志时,我们将获得更加完整的结果:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

Docopt (Docopt)

This section is where docopt shines. Because we wrote the documentation as the definition of the command-line interface itself, we already have the help documentation completed. In addition -h and --help are already provided.

本节是docopt的亮点。 因为我们将文档编写为命令行界面本身的定义,所以我们已经完成了帮助文档。 另外,已经提供了-h--help

1
1
2
2
3
3
4
4
5
5
6
6

请点击 (Click)

Adding help documentation to click is very similar to argparse. We need to add the help parameter to all of our @click.option decorators.

单击添加帮助文档与argparse非常相似。 我们需要将help参数添加到所有@click.option装饰器中。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18

However, click DOES NOT provide us -h by default. We need to use the context_settings parameter to override the default help_option_names.

但是,默认情况下,单击“ 提供-h 。 我们需要使用context_settings参数来覆盖默认的help_option_names

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

Now the click help documentation is complete.

现在,单击帮助文档已完成。

1
1
2
2
3
3
4
4
5
5
6
6
7
7

错误处理 (Error Handling)

Error handling is an important part of any application. This section will explore the default error handling of each application and implement additional logic if needed. We’ll explore three error cases:

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

  1. Not enough required arguments given.
  2. Invalid options/flags given.
  3. A flag with a value is given.
  1. 给出的参数不足。
  2. 给定了无效的选项/标志。
  3. 给出一个带有值的标志。

精氨酸 (Argparse)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

Not very exciting, as argparse handles all of our error cases out of the box.

这不是很令人兴奋,因为argparse可以开箱即用地处理所有错误情况。

Docopt (Docopt)

1
1
2
2
3
3
4
4
5
5

Unfortunatly, we have a bit of work to get docopt to an acceptable minimum level of error handling. The reccomended method for validation in docopt is the schema module. *Make sure to install – pip install schema. In addition they provide a very basic validation example. The following is our application with schema validation:

不幸的是,我们需要做一些工作才能使docopt达到可接受的最低级别的错误处理水平。 docopt中推荐的验证方法是架构模块。 *请确保安装– pip install schema 。 此外,它们提供了一个非常基本的验证示例 。 以下是我们的具有模式验证的应用程序:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24

With this validation in place we now get some error messages.

有了此验证,我们现在会收到一些错误消息。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9

While these messages are not very descriptive and may be hard to debug for larger applications, it’s better than no validation at all. The schema module does provide other mechanisms for adding more descriptive error messages but we won’t cover those here.

尽管这些消息不是很具描述性,可能难以为大型应用程序调试,但总比没有验证要好。 模式模块确实提供了用于添加更多描述性错误消息的其他机制,但此处不再赘述。

请点击 (Click)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

Just like argparse, click handles error input by default.

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



With that, we have completed the construction of the command-line application we set out to build. Before we conclude let’s take a look at another possible option.

至此,我们已经完成了将要构建的命令行应用程序的构建。 在得出结论之前,让我们看一下另一个可能的选择。

调用 (Invoke)

Can we use invoke, a simple task running library, to build the greeter command-line application? Let’s find out!

我们可以使用一个简单的任务运行库invoke来构建greeter命令行应用程序吗? 让我们找出答案!

To start let’s begin with the simplest version of the greeter:

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

tasks.py

task.py

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

With this very simple file we get a two tasks and very minimal help. From the same directory as tasks.py we get the following results:

通过这个非常简单的文件,我们得到了两个任务和非常少的帮助。 在与task.py相同的目录中,我们得到以下结果:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

Now let’s add in our options/flags – --greeting and --caps. In addition, we can pull out the greeting logic into it’s own function, just as we did with the other tools.

现在让我们添加选项/标志– --greeting--caps 。 此外,我们可以像其他工具一样将问候语逻辑引入其自身的功能中。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18

Now we actually have the complete interface we designated in the beginning!

现在,我们实际上已经拥有一开始指定的完整接口!

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

帮助文档 (Help Documentation)

In order to compete with argparse, docopt, and click, we’ll also need to be able to add complete help documentation. Luckily this is also available in invoke by using the help parameter of the @task decorator and adding docstrings to the decorated functions.

为了与argparse,docopt和click竞争,我们还需要能够添加完整的帮助文档。 幸运的是,通过使用@task装饰器的help参数并将文档字符串添加到装饰的函数中,也可以在调用中使用它。

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11

版本选项 (Version Option)

Implementing a --version option is not quite as simple and comes with a caveat. The basics are that we will add version=False as an option to each of the tasks that calls a new print_version function if True. In order to make this work we cannot have any positional arguments without defaults or we get:

实现--version选项并不那么简单,并且需要注意。 基础知识是,我们将在每个任务中将version=False添加为一个选项,如果True则调用新的print_version函数。 为了完成这项工作,我们不能没有默认值而使用任何位置参数,否则我们将得到:

1
1
2
2

Also note that we are calling --version on our commands hello and goodbye because invoke itself has a version command:

还要注意,我们在命令hellogoodbye调用--version ,因为invoke本身具有版本命令:

1
1
2
2

The completed implementation of a version command follows:

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

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17

Now we are able to ask invoke for the version of our tool:

现在我们可以要求invoke来获取我们工具的版本:

1
1
2
2

结论 (Conclusion)

To review, let’s take a look at the final version of each of the tools we created.

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

精氨酸 (Argparse)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28

Docopt (Docopt)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40
41
41
42
42
43
43
44
44
45
45
46
46
47
47
48
48
49
49
50
50
51
51
52
52
53
53
54
54
55
55
56
56
57
57
58
58
59
59
60
60
61
61
62
62
63
63

请点击 (Click)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36

调用 (Invoke)

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12
13
13
14
14
15
15
16
16
17
17
18
18
19
19
20
20
21
21
22
22
23
23
24
24
25
25
26
26
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
35
35
36
36
37
37
38
38
39
39
40
40

我的推荐 (My Recomendation)

Now, to get this out of the way, my personal go-to library is click. I have been using it on large, multi-command, complex interfaces for the last year. (Credit goes to @kwbeam for introducing me to click). I prefer the decorator approach and think it lends a very clean, composable interface. That being said, let’s evaluate each option fairly.

现在,要解决这个问题,请单击我的个人转到库。 去年,我一直在大型,多命令,复杂的界面上使用它。 (信用转到@kwbeam ,向我介绍点击)。 我更喜欢装饰器方法,并认为它提供了一个非常干净,可组合的界面。 话虽如此,让我们公平地评估每个选项。

稀疏的 (arparse)

Arparse is the standard library (included with Python) for creating command-line utilities. For that fact alone, it is arguably the most used of the tools examined here. Argparse is also very simple to use as lots of magic (implicit work that happens behind the scenes) is used to construct the interface. For example, both arguments and options are defined using the add_arguments method and argparse figures out which is which behind the scenes.

Arparse是用于创建命令行实用程序的标准库(Python附带)。 仅就这个事实而言,它可以说是这里研究最多的工具。 Argparse的使用也非常简单,因为大量的魔术(在幕后发生的隐式工作)用于构造界面。 例如,参数和选项都是使用add_arguments方法定义的,而argparse会找出在幕后的是哪一个。

docopt (docopt)

If you think writing documentation is great, docopt is for you! In addition docopt has implementations for many other languages – meaning you can learn one library and use it across many languages. The downside of docopt is that it is very structured in the way you have to define your command-line interface. (Some might say this is a good thing!)

如果您认为编写文档很棒,那么docopt非常适合您! 此外,docopt还具有许多其他语言的实现,这意味着您可以学习一个库并在多种语言中使用它。 docopt的缺点是,在定义命令行界面时,它的结构非常结构化。 (有人可能说这是一件好事!)

点击 (click)

I’ve already said that I really like click and have been using it in production for over a year. I encourage you to read the very complete Why Click? documentation. In fact, that documentation is what inspired this blog post! The decorator style implementation of click is very simple to use and since you are decorating the function you want executed, it makes it very easy to read the code and figure out what is going to be executed. In addition, click supports advanced features like callbacks, command nesting, and more. Click is based on a fork of the now deprecated optparse library.

我已经说过,我非常喜欢click,并且已经在生产中使用了一年以上。 我鼓励您阅读非常完整的“ 为什么单击”? 文档。 实际上,这些文档正是这篇博客文章的灵感源泉! click的装饰器样式实现非常易于使用,并且由于您正在装饰要执行的功能,因此可以非常轻松地阅读代码并弄清楚将要执行的代码。 此外,click支持高级功能,如回调,命令嵌套等。 Click基于现已弃用的optparse库的分支。

调用 (invoke)

Invoke surprised me in this comparison. I thought that a library designed for task execution might not be able to easily match full command-line libraries – but it did! That being said, I would not recommend using it for this type of work as you will certainly run into limitations for anything more complex than the example presented here.

在这个比较中,Invoke使我感到惊讶。 我认为为任务执行而设计的库可能无法轻松匹配完整的命令行库,但是可以! 话虽如此,我不建议您将其用于此类工作,因为您肯定会遇到比此处示例更复杂的限制。

奖励:包装 (Bonus: Packaging)

Since not everyone is packaging up there python source with setuptools (or other solutions), we decided not to make this a core component of the article. In addition, we don’t want to cover packaging as a complete topic. If you want to learn more about packaging with setuptools go here or with conda go here or you can read my previous blog post on conda packaging. What we will cover here is how to use the entry_points option to make a command-line application an executable command on install.

由于并非所有人都使用setuptools (或其他解决方案)将python源打包在一起,因此我们决定不将其作为本文的核心组件。 另外,我们不想将包装作为一个完整的主题。 如果您想了解更多关于使用setuptools 进行包装的信息,请访问此处或使用conda 进行 访问,或者您可以阅读我以前关于conda包装的博客文章我们将在这里讨论的是如何使用entry_points选项使命令行应用程序在安装时成为可执行命令

入口点基础 (Entry Point Basics)

An entry_point is essentially a map to a single function in your code that will be given a command on your system PATH. An entry_point has the form – command = package.module:function

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

The best way to explain this is to just look at our click example and add an entry point.

解释此问题的最佳方法是仅查看我们的点击示例并添加一个入口点。

打包点击命令 (Packaging Click Commands)

Click makes packaging simple, as by default we are calling a single function when we execute our program:

Click使打包变得简单,因为默认情况下,我们在执行程序时会调用一个函数:

1
1
2
2

In addition to the rest of the setup.py (not covered here), we would add the following to create an entry_point for our click application.

除了setup.py的其余部分(此处未介绍)之外,我们还将添加以下内容为click应用程序创建一个entry_point。

Assuming the following directory structure-

假设以下目录结构-

1
1
2
2
3
3
4
4
5
5

-we will create the following entry_point:

-我们将创建以下entry_point:

1
1
2
2
3
3
4
4
5
5

When a user installs the package created with this entry_point, setuptools will create the following executable script (called greet) and place it on the PATH of the user’s system.

当用户安装使用该entry_point创建的软件包时,setuptools将创建以下可执行脚本(称为greet )并将其放置在用户系统的PATH上。

1
1
2
2
3
3
4
4
5
5
6
6

After installation the user will now be able to run the following:

安装之后,用户现在可以运行以下命令:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10

打包Argparse命令 (Packaging Argparse Commands)

The only thing we need to do differently from click is to pull all of the application initialization into a single function that we can call in our entry_point.

我们唯一需要做的事情与单击不同,那就是将所有应用程序初始化都拉到一个可以在entry_point中调用的函数中。

This:

这个:

1
1
2
2
3
3

Becomes:

成为:

1
1
2
2
3
3
4
4
5
5
6
6

Now we can use the same pattern for the entry_point we defined for click.

现在,我们可以为定义用于click的entry_point使用相同的模式。

打包Docopt命令 (Packaging Docopt Commands)

Packaging docopt commands requires the same process as argparse.

打包docopt命令所需的过程与argparse相同。

This:

这个:

1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11
11
12
12

翻译自: https://www.pybloggers.com/2015/09/comparing-python-command-line-parsing-libraries-argparse-docopt-and-click/

python docopt

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值