欢迎查阅 Click 中文文档

Click 是一个利用很少的代码以可组合的方式创造优雅命令行工具接口的 Python 库。 它是高度可配置的,但却有合理默认值的“命令行接口创建工具”。

它致力于将创建命令行工具的过程变的快速而有趣,免除你因无法实现一个 CLI API 的挫败感。

Click 的三个特性:

  • 任意嵌套命令
  • 自动生成帮助页面
  • 支持在运行时延迟加载子命令

那么它到底什么样呢? 下面有一个简单的 Click 项目例子:

import click

@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':
    hello()

当它运行的时候是这样的:

$ python hello.py --count=3
Your name: John
Hello John!
Hello John!
Hello John!

它会自动生成美观的格式化帮助页面:

$ python hello.py --help
Usage: hello.py [OPTIONS]

  Simple program that greets NAME for a total of COUNT times.

Options:
  --count INTEGER  Number of greetings.
  --name TEXT      The person to greet.
  --help           Show this message and exit.

你可以通过 PyPI 安装它:

pip install click

文档内容

这部分文档将指引你浏览所有 Click 的使用方法。

为什么用 Click?

除此之外还有非常多的命令行工具,为什么还要创建 Click?

这个问题很容易回答:因为没有一个除此之外没有一个包含以下特性的单独为 Python 服务的命令行工具:

  • 没有限制可以简单组合
  • 完全遵循 Unix 命令行约定
  • 支持从环境变量中加载值
  • 支持特定值的提示
  • 充分地可嵌套可组合
  • 兼容python 2 和 3
  • 支持外部文件处理
  • 与一些常用的工具帮手结合 (获得 terminal 大小, ANSI 字符颜色, 直接输入按键, 屏幕清理, 获取 config 路径, 启动 apps 和 editors, 等.)

有很多 Click 的替代选择,如果你更喜欢它们,可以去看一看。最常见的是标准库中的 optparseargparse

Click 实际上是通过对 optparse 的一个分支进行封装而实现的,它本身并不进行解析。不基于 argparse 的原因是 argparse 从设计上不允许多个命令的嵌套, 同时在兼容处理 POSIX 参数时有一些不足。

Click 的设计原则是帮助你在使用过程中更有趣,但是并不是以你的角度出发。它也不太灵活。比如说目前情况下,它不允许你定制太多帮助页面的内容。这样做事故意的,因为 Click 的设计允许你去嵌套命令行程序。The idea is that you can have a system that works together with another system by tacking two Click instances together and they will continue working as they should.

过多的定制会影响这个功能。

Click 的创建是用来支持 Flask microframework 生态系统,因为没有工具可以提供需求的功能所需。

为了弄明白 Click 到底是什么样的?我强烈推荐你去看非常有用的 复杂的应用程序 章节。

为什么不用 Argparse?

Click 基于 optparse 而不是 argparse。这是因为一个用户不需要关心的实现细节。Click 不使用 argparse 的原因是在处理任意的命令行接口时有一些问题:

  • argparse有内置的魔术行为来猜测什么是参数或选项。这使得在处理不完整命令行命令时就成了一个问题,因为没有一个完整的命令行命令就无法得知解析器将如何运行。

这和 Click 所需的解析器背道相驰。 * argparse 目前还不支持禁用 interspersed 参数。没有这个特性将无法保证安全地运行 Click 的嵌套解析特性。

为什么不使用 Docopt 等?

Docopt 和其他与其相似的工具它们的运行方式很酷,但是这些工具中几乎没有一个能实现 Click 的嵌套命令和可组合的特性。 以优秀的开发经验来说,Click 是第一个致力于实现一个应用可组合性级别超越其本身所支持的范围的 Python 库。

例如,Docopt 通过解析帮助页面,然后从从中获取规则。这样做的副作用是 docopt 在解析命令行接口时非常的严格。优点是 docopt 给了你对帮助页面很大的控制权利;缺点是 对当前 terminal 宽度不能够重新包装输出结果,这使得翻译变得很困难。除此以外 docopt 在基本解析上是受限制的。它不能处理参数的执行、回调或类型。这意味着需要另外写 很多代码来处理帮助页面的解析结果。

然而,最重要的是,它使可组合性变得困难。虽然 docopt 确实支持分配到子命令,但它不直接支持任何基于什么是可用的子命令自动枚举或者它不能使子命令以一致的方式工作。

这样很好,但这和 Click 想做的不一样。Click 致力于通过以下几点完全支持可组合的命令行用户接口:

  • Click 不只是解析,它还将分配合适的代码。
  • Click 有一个强大的调用上下文概念,这使得子命令响应来自父命令的数据。
  • Click 具有可用于所有参数和命令的强大信息。这使得它可以对所有的 CLI 生成完整统一的帮助页面,在必要的时候去帮助用户转换输入数据。
  • Click 能够很好的识别参数类型,如果出错可以为用户提供统一的错误信息。一个由不同的开发者写的子命令在出现问题时不会因为人工处理错误而输出不同的错误信息。
  • Click 可以提供足够的元信息给整个程序。它可以随着时间的推移而进化,以改善用户体验不需要逼迫开发者去适应他们的程序。例如:如果 Click 决定去改变帮助页面

的格式化方式,所有的 Click 程序都会自动从中受益。

Click 的目标是创造统一的系统,而 docopt的目标是构建最漂亮的手工制作的命令行接口。这两个目标以微妙的方式相互冲突。 Click 主动防止用户实现特定的样式,目的是创造一个统一的命令行接口。例如在重新格式化你的帮助页面上你基本上不需要投入任何精力。

为什么使用硬编码的行为?

另一个问题是为什么 Click 与 optparse 背道相驰,使用硬编码特定的行为代替可配置的行为。有很多原因,其中最大的问题是太多的可配置能力使得很难实现一个统一的命令行接口。

最好的例子就是 optparse 的 callback 可以接受任意数量的参数的性质。由于语法歧义 在命令行上,没有办法实现完全可变参数。总是需要做出权衡,在 argparse 中这些权衡非常关键,这使得 Click 不能再它的基础上实现。

特别是,Click 尝试去保以一种可接受的方式来构建命令行接口,使这些接口可以更好的被测试和文档化。

为什么不自动纠正?

问题来自于 Click 为什么不自动纠正给定的参数,甚至于 optparse 和 argparse 都支持自动扩展长参数。 这主要是因为向后兼容的责任。如果人们开始依赖自动纠正参数,之后某个人又添加了一个新参数,脚本可能会停止工作。这类问题很难去查找,因此 Click 并不想在这上面使用“魔法”。

这种行为可以在更高的层次上实现,用来支持显式别名(explicit aliases)之类的东西。更多的信息你查看 命令别名

快速上手

你可以直接从 PyPI 中进行安装::

pip install click

强烈推荐将其安装在 virtualenv 中。

virtualenv

你可能需要用到 Virtualenv 来开发 Click 应用程序。

virtualenv 解决了什么问题呢? 有可能是你想将它应用于除了 Click 脚本以外的其他项目。 你负责的项目越多,你越有可能会应用到不同版本的 Python,或者不同版本的 Python 库, 我们可能面临一个问题:很多时候库会出现兼容性问题,任何应用程序都有可能发生版本冲突。那么如果两个或两个以上的项目具有相互冲突的依赖关系,你会怎么做?

这个时候 Virtualenv 派上用场了! Virtualenv 支持多个并行的 Python 安装,每个项目一个。 它实际上并不安装单独的 Python 副本,但它提供了一种巧妙的方法来隔离不同的项目环境。 让我们看看virtualenv是如何工作的。

如果您使用的是 Mac OS X 或 Linux,则有可能是以下两个命令之一适用于您::

$ sudo easy_install virtualenv

或者更好的方式:

$ sudo pip install virtualenv

以上任意一种方法都可以安装 virtualenv。甚至它已经在你的包管理器中。 如果你是 Ubuntu 用户, 尝试下列命令进行安装:

$ sudo apt-get install python-virtualenv

如果你在Windows上(或者上述方法都不行),你必须先安装 pip . 获取更多信息, 详见 installing pip. 安装完成后,运行 上面的``pip`` 指令, 但没有

sudo 前缀.

一旦你安装了 virtualenv, 只需启动一个 shell 并创建你自己的环境。 我通常在以下地方创建一个项目文件夹和一个 venv 文件夹:

$ mkdir myproject
$ cd myproject
$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools, pip............done.

现在,只要你想在一个项目上工作,你只需要激活相应的环境。在 OS X 和 Linux 上,执行以下操作::

$ . venv/bin/activate

如果你是 Windows 用户, 执行下列操作:

$ venv\scripts\activate

无论哪种方式,你现在应该使用你的 virtualenv(注意你的shell的提示已经改变,以显示新生成的环境)。

如果你想返回初始环境, 使用下列命令:

$ deactivate

这样做以后你的 shell 的提示应该变得和以前一样.

现在,我们继续。输入以下命令获取在 virtualenv 中 Click 的运行环境::

$ pip install Click

只需几秒的等待即可。

视频和例子

有一个视频可以展示 Click 的基本 API 以及如何使用它创建简单的应用程序。 它还探讨了如何使用子命令构建命令。

Click 应用程序的例子可以在文档中找到,也可以在 GitHub 的 readme 文件中找到::

基本概念

Click 是通过装饰器声明命令的。在内部,高级用例有一个非装饰器接口,但不鼓励高级用法。

一个函数通过装饰器成为一个 Click 命令行工具 click.command()。就是这么简单,用这个装饰器来装饰一个函数使它成为一个可调用的脚本::

import click

@click.command()
def hello():
    click.echo('Hello World!')

接着装饰器将函数转化成 Command 可以被调用的函数:

if __name__ == '__main__':
    hello()

它看起来像:

$ python hello.py
Hello World!

相应的帮助页面:

$ python hello.py --help
Usage: hello.py [OPTIONS]

Options:
  --help  Show this message and exit.

Echoing

为什么这个例子使用 echo() 而不是常规的 print() 功能? 原因很简单, Click 支持不同版本的 Python,并且即使在环境配置错误的情况下也是非常易用的。即使一切都完全被破坏,Click 在基础层面上起作用。

这意味着 echo() 函数应用了一些错误修正,以防终端配置错误而不是因为 UnicodeError 退出程序。

另一个好处是,从 Click 2.0开始,echo 函数也对 ANSI 字体颜色有很好的支持。如果输出流是一个文件,它会自动去除 ANSI 代码空格,并且支持色彩,ANSI 色彩也可以在Windows上使用。有关更多信息,请参阅:ref:ansi-colors

如果你不需要这个,你也可以使用 print() 构造/运行.

嵌套命令

命令可以附加到其他 Group 类型的命令。这允许任意嵌套脚本。下面例子中的脚本实现了两个管理数据库的命令:

@click.group()
def cli():
    pass

@click.command()
def initdb():
    click.echo('Initialized the database')

@click.command()
def dropdb():
    click.echo('Dropped the database')

cli.add_command(initdb)
cli.add_command(dropdb)

正如你所看到的那样, group() 装饰器就像 command() 装饰器一样工作, 但创建一个 Group 对象,可以通过 Group.add_command() 赋予多个可以附加的子命令。

对于简单的脚本,也可以使用 Group.command() 装饰器自动附加和创建命令。上面的脚本可以写成这样:

@click.group()
def cli():
    pass

@cli.command()
def initdb():
    click.echo('Initialized the database')

@cli.command()
def dropdb():
    click.echo('Dropped the database')

添加参数

要添加参数,请使用 option()argument() 装饰器:

@click.command()
@click.option('--count', default=1, help='number of greetings')
@click.argument('name')
def hello(count, name):
    for x in range(count):
        click.echo('Hello %s!' % name)

它看起来像:

$ python hello.py --help
Usage: hello.py [OPTIONS] NAME

Options:
  --count INTEGER  number of greetings
  --help           Show this message and exit.

生成 Setuptools

就目前你写的代码,文件末尾有一个类似这种的代码块: if __name__ == '__main__':。这是一个传统独立的 Python 文件格式。使用 Click 你可以继续这样做, 但使用 setuptools 是一个更好的办法。

有两个主要的原因(还有更多其他的原因):

第一个原因是 setuptools 自动为 Windows 生成可执行的包装器,所以你的命令行工具也可以在Windows上工作。

第二个原因是 setuptools 脚本和 Unix 上的 virtualenv 一起工作,而不需要激活 virtualenv 。这是一个非常有用的概念,它允许你将你的脚本和所有依赖绑定到一个虚拟环境中。

Click 和它搭配起来简直天衣无缝。 接下来的文档将假设你正在通过 setuptools 写应用程序。

假如你将使用setuptools,强烈建议去阅读 Setuptools 集成 章节,然后再阅读其余的例子。

Setuptools 集成

编写命令行程序时,建议将它们编写为 setuptools 型分发的模块,而不是使用 Unix shebangs。

你为何要这么做呢? 有如下几个原因:

  1. 传统方法的问题之一是Python解释器加载的第一个模块名称不正确。这可能像一个小问题, 但具有相当重要的意义。

    第一个模块没有被其实际名称调用,但解释器将其重命名为 __main__ 虽然这是一个完全有 效的名字,但这意味着如果另一段代码想要从该模块导入,它将在其真实名称下第二次触发导入, 并且突然间您的代码将被导入两次。

  2. 不是在所有的平台上,程序都是易于执行的。在Linux和OS X上,您可以将注释添加到文件的开头 (开头这么写 #!/usr/bin/env python) ,这样您的脚本就像一个可执行文件(假设它具有可执行位设置)。 但是,这不适用于Windows系统。在Windows上,您可以将解释器与文件扩展名关联起来() (就像任何以 .py 结尾的文件,通过Python解释器执行) ,如果在要在virtualenv中使用该脚本, 则会遇到问题。

    实际上,在 virtualenv 中运行脚本也是 OS X 和 Linux 一个问题。使用传统方法,您需要激活整个 virtualenv, 以便使用正确的Python解释器。这对用户不是非常友好。

  3. 主要的技巧只有在脚本是在Python模块时才有效。如果你的应用程序变得太大,你想开始 使用一个包,你会遇到问题。

介绍

要将脚本与setuptools捆绑在一起,您只需要Python程序包和 setup.py 文件。

想象一下这个目录结构:

yourscript.py
setup.py

yourscript.py 的内容为:

import click

@click.command()
def cli():
    """Example script."""
    click.echo('Hello World!')

setup.py 的内容为:

from setuptools import setup

setup(
    name='yourscript',
    version='0.1',
    py_modules=['yourscript'],
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        yourscript=yourscript:cli
    ''',
)

神奇的是 entry_points 参数. 下面``console_scripts``, 每行标识一个控制台脚本。第一部分是在等号 (=) 前面的应该生成的脚本名称。第二部分是在冒号后面(:)的导入路径。

仅此而已。

测试脚本

为了测试脚本,你可以创建一个新的virtualenv然后安装你的包:

$ virtualenv venv
$ . venv/bin/activate
$ pip install --editable .

之后,您的命令应该可用:

$ yourscript
Hello World!

包中的脚本

如果您的脚本正在增多,并且您希望切换到包含在Python包中的脚本,那么所需的更改很少。我们假设你的目录结构变成这样:

yourpackage/
    __init__.py
    main.py
    utils.py
    scripts/
        __init__.py
        yourscript.py

在这种情况下,在 setup.py 文件中,使用 pacckages 代替 py_modules ,同时自动包会找到 setuptools的支持。除此之外,还建议它含其他包数据。

如下这些是对 setup.py 文件内容的修改:

from setuptools import setup, find_packages

setup(
    name='yourpackage',
    version='0.1',
    packages=find_packages(),
    include_package_data=True,
    install_requires=[
        'Click',
    ],
    entry_points='''
        [console_scripts]
        yourscript=yourpackage.scripts.yourscript:cli
    ''',
)

参数

Click 支持两种类型的脚本参数: 选项和参数。 命令行脚本的作者通常在使用哪个脚本时会有一些混淆,所以这里是对这些差异的简要概述。 正如其名称所示,选项是可选的。虽然参数在合理的范围内是可选的,但是它们在选择 的方式上会受到更多的限制。

为了帮助您在选项和参数之间做出决定,建议仅使用参数,例如转到子命令或输入 文件名, / , URLs, 然后让所有其他选项成为选项。

差异

参数功能略少于选项。以下功能仅适用于选项:

  • 选项可自动提示缺少输入
  • 选项可作为标志(布尔值或其他)
  • 选项值可以从环境变量中拉出来,但参数不能
  • 选项能完整记录在帮助页面中,但参数不能(这显而易见,因为参数可能过于具体而不能自动记录)

另一方面,与选项不同,参数可以接受任意数量的参数。选项可以严格地只接受固定数量的参数(默认为1)。

参数类型

参数可以是不同的类型。类型可以用不同的行为来实现,有些是开箱即用的:

str / click.STRING:
表示unicode字符串的默认参数类型。
int / click.INT:
只接受整数的参数。
float / click.FLOAT:
只接受浮点值的参数。
bool / click.BOOL:
接受布尔值的参数。这是自动使用布尔值的标志。如果字符值是: 1, yes, ytrue 转化为 True0, no, nfalse 转化为 False
click.UUID:
接受UUID值的参数。这不是自动识别,而是表示为 uuid.UUID.
class click.File(mode='r', encoding=None, errors='strict', lazy=None, atomic=False)

Declares a parameter to be a file for reading or writing. The file is automatically closed once the context tears down (after the command finished working).

Files can be opened for reading or writing. The special value - indicates stdin or stdout depending on the mode.

By default, the file is opened for reading text data, but it can also be opened in binary mode or for writing. The encoding parameter can be used to force a specific encoding.

The lazy flag controls if the file should be opened immediately or upon first IO. The default is to be non lazy for standard input and output streams as well as files opened for reading, lazy otherwise.

Starting with Click 2.0, files can also be opened atomically in which case all writes go into a separate file in the same folder and upon completion the file will be moved over to the original location. This is useful if a file regularly read by other users is modified.

See 文件参数 for more information.

class click.Path(exists=False, file_okay=True, dir_okay=True, writable=False, readable=True, resolve_path=False, allow_dash=False, path_type=None)

The path type is similar to the File type but it performs different checks. First of all, instead of returning an open file handle it returns just the filename. Secondly, it can perform various basic checks about what the file or directory should be.

在 6.0 版更改: allow_dash was added.

参数:
  • exists -- if set to true, the file or directory needs to exist for this value to be valid. If this is not required and a file does indeed not exist, then all further checks are silently skipped.
  • file_okay -- controls if a file is a possible value.
  • dir_okay -- controls if a directory is a possible value.
  • writable -- if true, a writable check is performed.
  • readable -- if true, a readable check is performed.
  • resolve_path -- if this is true, then the path is fully resolved before the value is passed onwards. This means that it's absolute and symlinks are resolved.
  • allow_dash -- If this is set to True, a single dash to indicate standard streams is permitted.
  • type -- optionally a string type that should be used to represent the path. The default is None which means the return value will be either bytes or unicode depending on what makes most sense given the input data Click deals with.
class click.Choice(choices)

The choice type allows a value to be checked against a fixed set of supported values. All of these values have to be strings.

See 选择选项 for an example.

class click.IntRange(min=None, max=None, clamp=False)

A parameter that works similar to click.INT but restricts the value to fit into a range. The default behavior is to fail if the value falls outside the range, but it can also be silently clamped between the two edges.

See 范围选项 for an example.

自定义参数类型可以通过子类实现 click.ParamType 。对于简单的情况,也支持传递一个失败的 ValueError Python函数,尽管不鼓励这么做。

参数名称

参数(包括选项和参数)都接受一些参数声明的位置参数。每个带有单个短划线的字符串 都被添加为短参数; 每个字符串都以一个双破折号开始。如果添加一个没有任何破折号的 字符串,它将成为内部参数名称,也被用作变量名称。

如果一个参数没有给出一个没有破折号的名字, 那么通过采用最长的参数并将所有的破折号 转换为下划线来自动生成一个名字。 如果一个有 ('-f', '--foo-bar') 的选项,那么该参数名被设置为 foo_bar , 如果一个有 ('-x',) 的选项, 那么该参数名被设置为 x , 如果一个有 ('-f', '--filename', 'dest') 的选项,那么该参数名被设置为 dest

实现自定义类型

要实现一个自定义类型,你需要继承这个 ParamType 类 类型可以调用有或没有上下文和参数对象,这就是为什么他们需要能够处理这个问题。

下面的代码实现了一个整数类型,除了普通整数之外,还接受十六进制和八进制数字, 并将它们转换为常规整数::

import click

class BasedIntParamType(click.ParamType):
    name = 'integer'

    def convert(self, value, param, ctx):
        try:
            if value[:2].lower() == '0x':
                return int(value[2:], 16)
            elif value[:1] == '0':
                return int(value, 8)
            return int(value, 10)
        except ValueError:
            self.fail('%s is not a valid integer' % value, param, ctx)

BASED_INT = BasedIntParamType()

如你所见, 一个子类需要实现这个 ParamType.convert() 方法,并且可以选择提供这个 ParamType.name 属性。后者可用于文档的目的。

选项

通过 option() 装饰器可以给命令增加选项。通过配置参数来控制不同的选项。Click 中的选项不同于 位置参数

基本的值选项

最基本的选项是值选项。这种类型的选项接受一个是值得参数。如果没有指定值的类型,那么将使用默认类型 STRING。默认情况下,参数的名称为第一个 长选项,如果没有长选项则为第一个短选项。

@click.command()
@click.option('--n', default=1)
def dots(n):
    click.echo('.' * n)

在命令行中运行:

$ dots --n=2
..

这上述例子中选项值的类型是 INT,因为值的默认值为数字。

多个值的选项

有时候,你需要有多个值得选项。这种选项只支持固定数量的参数。通过 nargs 参数来配置。多个值将被放入一个元组(tuple)中。

@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
    click.echo('%s / %s' % pos)

在命令行中运行:

$ findme --pos 2.0 3.0
2.0 / 3.0

使用元组(tuple)代替多个值的选项

4.0 新版功能.

正如你所看到的,使用 nargs 来设置一个每个值都是数字的选项,得到的元组(tuple)中都是一样的数字类型。这可能不是你想要的。 通常情况下,你希望元组中包含不同类型的值。你可以直接使用下列的特殊元组达成目的:

@click.command()
@click.option('--item', type=(unicode, int))
def putitem(item):
    click.echo('name=%s id=%d' % item)

在命令行中运行:

$ putitem --item peter 1338
name=peter id=1338

使用元组的选项,nargs 会根据元组的长度自动生成,同时自动使用 click.Tuple。以下列子可等价表达上述例子:

@click.command()
@click.option('--item', nargs=2, type=click.Tuple([unicode, int]))
def putitem(item):
    click.echo('name=%s id=%d' % item)

多个选项

nargs 类似,有时候可能会需要一个参数传递多次,同时记录每次的值而不是只记录最后一个值。 比如,git commit -m foo -m bar 会记录两行 commit 信息:foobar。这个功能 可以通过 multiple 参数实现:

例如:

@click.command()
@click.option('--message', '-m', multiple=True)
def commit(message):
    click.echo('\n'.join(message))

在命令行中运行:

$ commit -m foo -m bar
foo
bar

计数

在一些非常罕见的情况下,使用重复的选项来计数是很有意思的。例如:

@click.command()
@click.option('-v', '--verbose', count=True)
def log(verbose):
    click.echo('Verbosity: %s' % verbose)

在命令行中运行:

$ log -vvv
Verbosity: 3

布尔值标记

布尔值标记用于开启或关闭选项。可以通过以 / 分割的两个标记来实现开启或关闭选项。(如果 / 在一个选项名中,Click 会自动识别其为布尔值标记,隐式默认 is_flag=True)。Click 希望你能提供一个开启和关闭标记然后设置默认值。

例如:

import sys

@click.command()
@click.option('--shout/--no-shout', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

在命令行中运行:

$ info --shout
LINUX2!!!!111
$ info --no-shout
linux2

如果你实在不想要一个关闭标记,你只需要定义开启标记,然后手动设置它为标记。

import sys

@click.command()
@click.option('--shout', is_flag=True)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)

在命令行中运行:

$ info --shout
LINUX2!!!!111

提示:如果 / 已经包含在你的选项名中(比如说如果你使用 Windows 风格的参数 / 是字符串的前缀),你可以使用 ; 来代替 /

@click.command()
@click.option('/debug;/no-debug')
def log(debug):
    click.echo('debug=%s' % debug)

if __name__ == '__main__':
    log()

在 6.0 版更改.

如果你想定义一个别名作为第二个选项名,你需要开头空格消除格式化字符串时的歧义:

例如:

import sys

@click.command()
@click.option('--shout/--no-shout', ' /-S', default=False)
def info(shout):
    rv = sys.platform
    if shout:
        rv = rv.upper() + '!!!!111'
    click.echo(rv)
$ info --help
Usage: info [OPTIONS]

Options:
  --shout / -S, --no-shout
  --help                    Show this message and exit.

功能开关

另一种布尔值标记,同时也是功能开关。通过对多个选项设置同一个参数名,同时设置一个标记来实现。提示通过提供 flag_value 参数,Click 会自动隐式设置 is_flag=True

设置一个默认值为 True 的默认标记。

import sys

@click.command()
@click.option('--upper', 'transformation', flag_value='upper',
              default=True)
@click.option('--lower', 'transformation', flag_value='lower')
def info(transformation):
    click.echo(getattr(sys.platform, transformation)())

在命令行中运行:

$ info --upper
LINUX2
$ info --lower
linux2
$ info
LINUX2

选择选项

有时候你想要一个值为某个列表内的某一个的参数。这种情况下,你可以使用 Choice 类型。它可以实例化一个包含有效值的列表。

例如:

@click.command()
@click.option('--hash-type', type=click.Choice(['md5', 'sha1']))
def digest(hash_type):
    click.echo(hash_type)

运行如下:

$ digest --hash-type=md5
md5

$ digest --hash-type=foo
Usage: digest [OPTIONS]

Error: Invalid value for "--hash-type": invalid choice: foo. (choose from md5, sha1)

$ digest --help
Usage: digest [OPTIONS]

Options:
  --hash-type [md5|sha1]
  --help                  Show this message and exit.

提示

有时候,你想通过命令行输入没有提供的参数。通过定义一个 prompt 参数可以实现这个功能。

例如:

@click.command()
@click.option('--name', prompt=True)
def hello(name):
    click.echo('Hello %s!' % name)

运行如下:

$ hello --name=John
Hello John!
$ hello
Name: John
Hello John!

如果你不喜欢默认的提示信息,你可以自己定义:

@click.command()
@click.option('--name', prompt='Your name please')
def hello(name):
    click.echo('Hello %s!' % name)

运行如下:

$ hello
Your name please: John
Hello John!

密码提示

Click 也支持隐藏输入信息和确认,这在输入密码时非常有用:

@click.command()
@click.option('--password', prompt=True, hide_input=True,
              confirmation_prompt=True)
def encrypt(password):
    click.echo('Encrypting password to %s' % password.encode('rot13'))

运行如下:

$ encrypt
Password: 
Repeat for confirmation: 
Encrypting password to frperg

因为这种情况非常普遍,因此你可以直接用 password_option() 装饰器取代:

@click.command()
@click.password_option()
def encrypt(password):
    click.echo('Encrypting password to %s' % password.encode('rot13'))

提示时获取动态的默认值

上下文中的 auto_envvar_prefixdefault_map 选项允许程序从环境变量或者配置文件中读取选项的值。 不过这会覆盖提示机制,你将不能够自主输入选项的值。

如果你想要用户自己设置默认值,同时如果命令行没有获取该选项的值仍然使用提示进行输入,你可以提供一个可供调用的默认值。比如说从环境变量中获取一个默认值:

@click.command()
@click.option('--username', prompt=True,
              default=lambda: os.environ.get('USER', ''))
def hello(username):
    print("Hello,", username)

回调选项和优先选项

有时候,你想要一个参数去完整地改变程序运行流程。比如,你想要一个 --version 参数去打印出程序的版本然后退出。

提示:--version 参数功能真正地实现是依靠 Click 中的 click.version_option()。下面的代码只是做一个简单的展示。

在下面你例子中,你需要明白两个概念:优先参数和回调。优先参数会比其他参数优先处理,回调是参数被处理后将调用回调函数。在优先需要一个参数时优先运行是很必须要的。 比如,如果 --version 运行前需要 --foo 参数,你需要让它优于 --version 运行。详细信息请查看 回调评估顺序

回调是有当前上下文 Context 和值两个参数的函数。上下文提供退出程序和访问其他已经生成的参数的有用功能。

下面是一个 --version 的简单例子:

def print_version(ctx, param, value):
    if not value or ctx.resilient_parsing:
        return
    click.echo('Version 1.0')
    ctx.exit()

@click.command()
@click.option('--version', is_flag=True, callback=print_version,
              expose_value=False, is_eager=True)
def hello():
    click.echo('Hello World!')

expose_value 参数可以避免没有用的 version 参数传入回调函数中。如果没有设置它,一个布尔值将传入 hello 脚本中。 resilient_parsing 用于在 Click 想在不影响整个程序运行的前提下解析命令行。这个例子中我将退出程序,什么也不做。

如下所示:

$ hello
Hello World!
$ hello --version
Version 1.0

Callback Signature Changes

In Click 2.0 the signature for callbacks changed. For more information about these changes see Upgrading to 2.0.

Yes 参数

对于一些危险的操作,询问用户是否继续是一个明智的选择。通过添加一个布尔值 --yes 标记就可以实现,用户如果不提供它,就会得到提示。

def abort_if_false(ctx, param, value):
    if not value:
        ctx.abort()

@click.command()
@click.option('--yes', is_flag=True, callback=abort_if_false,
              expose_value=False,
              prompt='Are you sure you want to drop the db?')
def dropdb():
    click.echo('Dropped all tables!')

在命令行中运行:

$ dropdb
Are you sure you want to drop the db? [y/N]: n
Aborted!
$ dropdb --yes
Dropped all tables!

因为这样的组合很常见,所以你可以用 confirmation_option() 装饰器来实现:

@click.command()
@click.confirmation_option(prompt='Are you sure you want to drop the db?')
def dropdb():
    click.echo('Dropped all tables!')

Callback Signature Changes

In Click 2.0 the signature for callbacks changed. For more information about these changes see Upgrading to 2.0.

从环境变量中获取值

Click 有一个非常有用的特性,除了接收常规的参数外它可以从环境变量中接收参数。这个功能可以让工具更容易自动化。比如,你可能想要通过 --config 参数获取配置文件 ,同时又想支持通过提供 TOOL_CONFIG=hello.cfg 键值对来获取配置文件。

Click 通过两种方式实现这种需求。一种是去自动创建选项所需的环境变量。开启这个功能需要在脚本运行时使用 auto_envvar_prefix 参数。每个命令和参数将被添加为以 下划线分割的大写变量。如果你有一个叫做 foo 的子命令,它有一个叫 bar 的选项,且有一个叫 MY_TOOL 的前缀,那么变量名就叫 MY_TOOL_FOO_BAR

用例:

@click.command()
@click.option('--username')
def greet(username):
    click.echo('Hello %s!' % username)

if __name__ == '__main__':
    greet(auto_envvar_prefix='GREETER')

在命令行中运行:

$ export GREETER_USERNAME=john
$ greet
Hello john!

另一种是通过在选项中定义环境变量的名字来手工从特定的环境变量中获取值。

用例:

@click.command()
@click.option('--username', envvar='USERNAME')
def greet(username):
    click.echo('Hello %s!' % username)

if __name__ == '__main__':
    greet()

在命令行中运行:

$ export USERNAME=john
$ greet
Hello john!

在这个例子中,也可以使用列表,列表中的第一个值将被选用。

从环境变量中获取多个值

由于选项可以接收多个值,从环境变量中获取多个值(字符串)稍微复杂一些。Click 通过定义 type 同时 multiplenargs 的值需要为 1 以外的值,Click 会运行 ParamType.split_envvar_value() 方法来进行分隔。

默认情况下所有的 type 都将使用空格来分割。但是 FilePath type 是例外,它们两个都遵守操作系统的路径分割规则。 在 Linux 和 OS X 的 Unix系统上,通过 (:) 分割,在 Windows 系统上,通过 (;) 分割。

用例:

@click.command()
@click.option('paths', '--path', envvar='PATHS', multiple=True,
              type=click.Path())
def perform(paths):
    for path in paths:
        click.echo(path)

if __name__ == '__main__':
    perform()

在命令行中运行:

$ export PATHS=./foo/bar:./test
$ perform
./foo/bar
./test

其他前缀参数

Click 能够使用除了 - 以外进行分割的前缀参数。如果你想处理有斜杠 / 或其他类似的参数,这个特性将非常有用。 注意一般情况下强烈不推荐使用,因为 Click 想要开发者尽可能地保持 POSIX 语法。但是在一些特定情况下,这个特性是很有用的:

@click.command()
@click.option('+w/-w')
def chmod(w):
    click.echo('writable=%s' % w)

if __name__ == '__main__':
    chmod()

在命令行中运行:

$ chmod +w
writable=True
$ chmod -w
writable=False

注意如果你想使用 / 作为前缀字符,如果你想要使用布尔值标记,你需要使用 ; 分隔符替换 /:

@click.command()
@click.option('/debug;/no-debug')
def log(debug):
    click.echo('debug=%s' % debug)

if __name__ == '__main__':
    log()

范围选项

使用 IntRange type 可以获得一个特殊的方法,它和 INT type 有点像,它的值被限定在一个特定的范围内(包含两端的值)。它有两种模式:

  • 默认模式(非强制模式),如果值不在区间范围内将会引发一个错误。
  • 强制模式,如果值不在区间范围内,将会强制选取一个区间临近值。也就是说如果区间是 0-5,值为 10 则选取 5,值为 -1 则选取 0

例如:

@click.command()
@click.option('--count', type=click.IntRange(0, 20, clamp=True))
@click.option('--digit', type=click.IntRange(0, 10))
def repeat(count, digit):
    click.echo(str(digit) * count)

if __name__ == '__main__':
    repeat()

在命令行中运行:

$ repeat --count=1000 --digit=5
55555555555555555555
$ repeat --count=1000 --digit=12
Usage: repeat [OPTIONS]

Error: Invalid value for "--digit": 12 is not in the valid range of 0 to 10.

如果区间的一端为 None,这意味着这一端将不限制。

使用回调函数进行验证

在 2.0 版更改.

如果你想自定义验证逻辑,你可以在回调参数中做这些事。回调方法中既可以改变值又可以在验证失败时抛出错误。

在 Click 1.0 中,你需要抛出 UsageError 错误,但是从 Click 2.0 开始,你也可以抛出 BadParameter 错误,这个错误增加了一些优点,它会自动 格式化包含参数名的错误信息。

例如:

def validate_rolls(ctx, param, value):
    try:
        rolls, dice = map(int, value.split('d', 2))
        return (dice, rolls)
    except ValueError:
        raise click.BadParameter('rolls need to be in format NdM')

@click.command()
@click.option('--rolls', callback=validate_rolls, default='1d6')
def roll(rolls):
    click.echo('Rolling a %d-sided dice %d time(s)' % rolls)

if __name__ == '__main__':
    roll()

在命令行中运行:

$ roll --rolls=42
Usage: roll [OPTIONS]

Error: Invalid value for "--rolls": rolls need to be in format NdM

$ roll --rolls=2d12
Rolling a 12-sided dice 2 time(s)

参数

参数的工作方式与 options 类似,但都是位置的。由于其语法性质,它们也仅支持options功能的子集,Click不会记录参数,希望你手动记录它们以避免跳出帮助页面。

基本参数

最基本的 option 是一个值的简单字符串参数。如果没有提供option,则使用默认值的类型。如果没有提供默认值,则类型被假定为 STRING.

例如:

@click.command()
@click.argument('filename')
def touch(filename):
    click.echo(filename)

它看起来像:

$ touch foo.txt
foo.txt

可变参数:

第二个常见的版本是接受具体(或不受限)参数的可变参数。这可以用``nargs``参数来控制. 如果设置为 -1, 则接受无限数量的参数。

该值然后作为元组(tuple)传递。请注意,只有一个参数可以设置为 nargs=-1, 它将作为最后一个参数.

例如:

@click.command()
@click.argument('src', nargs=-1)
@click.argument('dst', nargs=1)
def copy(src, dst):
    for fn in src:
        click.echo('move %s to folder %s' % (fn, dst))

它看起来像:

$ copy foo.txt bar.txt my_folder
move foo.txt to folder my_folder
move bar.txt to folder my_folder

请记住问题不在于如何实现这个应用原因是这个特别的例子中参数被定义为字符串。 文件名不能是字符串! 它们会出现在特定的系统中,但不会应用所有,下章将详细讲到。

关于非空变量参​​数的注意事项

如果你使用 argparse, 你可能会失去从``nargs`` 到 + 的支持,至少有一个参数是必需的。

它由 ``required=True``设置支持. 如果可以避免的话,不应该使用它,因为如果可变参数是空的,我们认为脚本应该降级成为noops。原因是很多时候,通过命令行输入通配符来调用脚本,如果通配符为空,则不会出错。

文件参数

由于所有的例子都已经使用了文件名,因此解释如何正确处理文件十分重要。命令行工具更有趣,如果他们使用文件unix的方式接受``-``作为特殊文件引用stdin /标准输出。

Click 支持通过 click.File 类型为你智能地处理文件. 它还为所有版本的Python正确处理unicode和字节,使得脚本保存十分方便。

例如:

@click.command()
@click.argument('input', type=click.File('rb'))
@click.argument('output', type=click.File('wb'))
def inout(input, output):
    while True:
        chunk = input.read(1024)
        if not chunk:
            break
        output.write(chunk)

它呈现的效果:

$ inout - hello.txt
hello
^D
$ inout hello.txt -
hello

文件路径参数

在前面的例子中,文件立即被打开。但是如果我们只想要文件名呢?原始方法是使用默认的字符串参数类型。但是,请记住Click是基于Unicode的,所以字符串将始终是Unicode值。不幸的是,文件名可以是Unicode或字节,具体取决于正在使用的操作系统。因此,这种类型是不够的。

相反,你应该使用 Path 自动处理这种模糊的类型。它不仅会返回字节或Unicode,而且还取决于更有意义的内容,但也可以为你进行一些基本检查,例如存在检查。

例如:

@click.command()
@click.argument('f', type=click.Path(exists=True))
def touch(f):
    click.echo(click.format_filename(f))

它呈现的效果:

$ touch hello.txt
hello.txt

$ touch missing.txt
Usage: touch [OPTIONS] F

Error: Invalid value for "f": Path "missing.txt" does not exist.

文件安全打开

FileType 类型有一个需要处理的问题,那就是决定何时打开一个文件。默认行为是对它友善。这意味着它将打开标准输入/标准输出和立即打开的文件。当一个文件不能被打开时,这将给用户直接的反馈,但是它只会在第一次执行一个IO操作时,通过自动将文件包装在一个特殊的包装器中来打开文件。

这种行为可以通过传递 lazy=True 或者 lazy=False 构造函数来强制。如果该文件被强制打开, 它将通过显示一个失败的IO操作 FileError.

由于文件打开的文件通常会立即清空文件,只有在开发人员确信这是预期的行为时才应禁用懒惰模式。

强制懒惰模式也是非常有用的,以避免资源处理混淆。如果一个文件在懒惰模式下打开,它会收到一个 close_intelligently 方法,可以帮助确定文件是否需要关闭。这对于参数是不需要的,但对于手动提示 prompt() 函数是必要的, 因为你不知道是否打开了一个类似stdout的流(之前已经打开)或需要关闭的实际文件。

从Click 2.0开始,也可以通过传递以原子模式打开文件atomic=True。在原子模式下,所有写入操作都将放入同一文件夹中的单独文件中,完成后,文件将移至原始位置。如果其他用户定期读取的文件被修改,这是非常有用的。

环境变量

与options一样,参数也可以从环境变量中获取值。然而,与选项不同的是,这只支持显示命名的环境变量.

用法事例:

@click.command()
@click.argument('src', envvar='SRC', type=click.File('r'))
def echo(src):
    click.echo(src.read())

命令行显示:

$ export SRC=hello.txt
$ echo
Hello World!

在这种情况下,它也可以是第一个选择的不同环境变量的列表。

一般来说,这个功能是不推荐的,因为它可能会导致用户很大的困惑。

Option-Like 参数

有时候,你想处理看起来像options的参数。例如,假设你有一个名为的文件-foo.txt。如果以这种方式将此作为参数传递,Click将把它作为一个options。

为了解决这个问题,Click执行任何POSIX样式的命令行脚本,并接受字符串--作为选项和参数的分隔符。在--标记之后,所有其他参数被接受为参数。

用法事例:

@click.command()
@click.argument('files', nargs=-1, type=click.Path())
def touch(files):
    for filename in files:
        click.echo(filename)

从命令行执行:

$ touch -- -foo.txt bar.txt
-foo.txt
bar.txt

命令和组

Click最重要的特点是任意嵌套命令行工具的概念。这是通过 CommandGroup (实际上是 MultiCommand) 实现的。

回调调用

对于一个普通的命令,只要命令运行就执行回调。如果脚本是唯一的命令,它总是会被触发(除非参数回调阻止了它)。 如果有人传递 --help 给脚本,就会发生这种情况。

对于组和多个命令,情况看起来不同。在这种情况下,只要子命令触发,就会触发回调(除非这种行为被改变)。 这实际上意味着当内部命令运行时外部命令运行:

@click.group()
@click.option('--debug/--no-debug', default=False)
def cli(debug):
    click.echo('Debug mode is %s' % ('on' if debug else 'off'))

@cli.command()
def sync():
    click.echo('Synching')

效果是这样的:

$ tool.py
Usage: tool.py [OPTIONS] COMMAND [ARGS]...

Options:
  --debug / --no-debug
  --help                Show this message and exit.

Commands:
  sync

$ tool.py --debug sync
Debug mode is on
Synching

传递参数

Click 点击严格分隔命令和子命令之间的参数。这意味着该选项和参数特定命令必须指定 之后 的命令名称本身,但 之前 任何其他命令的名字。

这个行为已经被预定义的 --help 选项观察到了。 假设我们有一个叫做的程序 tool.py, 其中包含一个叫做子命令 sub

  • tool.py --help 将返回整个程序的帮助(列出子命令)。
  • tool.py sub --help 将返回 sub 子命令的帮助。
  • tool.py --help sub 将把 --help 视作为主要方案的论据。 这时 Click 调用回调 --help, 打印帮助和中止程序,再点击可以处理子命令。

嵌套处理和上下文

从前面的示例中可以看到,基本命令组接受一个调试参数,该参数传递给其回调函数,但不传递给sync命令本身。sync命令只接受自己的参数。

这允许工具完全相互独立,但是一个命令如何与嵌套命令进行对话呢?答案是 Context

每次调用一个命令时,都会创建一个新的上下文并与父上下文链接。通常情况下,你看不到这些情况, 但他们在那里。上下文自动传递给参数回调和值。 命令还可以通过使用 pass_context() 装饰器标记自己来请求传递上下文。在这种情况下,上下文作为第一个参数传递。

上下文还可以携带一个程序指定的对象,可以用于程序的目的。这意味着你可以像这样构建一个脚本:

@click.group()
@click.option('--debug/--no-debug', default=False)
@click.pass_context
def cli(ctx, debug):
    ctx.obj['DEBUG'] = debug

@cli.command()
@click.pass_context
def sync(ctx):
    click.echo('Debug is %s' % (ctx.obj['DEBUG'] and 'on' or 'off'))

if __name__ == '__main__':
    cli(obj={})

如果提供了对象,那么每个上下文都将把对象传递给它的子对象,但是在任何级别都可以覆盖上下文的对象。 使用 context.parent 可以要达到父级。

除此之外,并不是传递一个对象,而是阻止应用程序修改全局状态。例如,你可以只是翻转一个全局 DEBUG 变量,并完成它。

装饰命令

正如你在前面的例子中看到的那样,装饰器可以改变命令的调用方式。幕后实际发生的事情是回调总是通过 Context.invoke() 自动调用命令的方法来调用(通过传递上下文)。

当你想编写自定义装饰器时,这是非常有用的。例如,一个常见的模式是配置一个表示状态的对象,然后将其存储在上下文中,然后使用自定义装饰器来查找该类型的最新对象并将其作为第一个参数传递。

例如, the pass_obj() 装饰器可以像这样实现:

from functools import update_wrapper

def pass_obj(f):
    @click.pass_context
    def new_func(ctx, *args, **kwargs):
        return ctx.invoke(f, ctx.obj, *args, **kwargs)
    return update_wrapper(new_func, f)

Context.invoke() 命令将以正确的方式自动调用该函数,因此该函数将被 f(ctx, obj)f(obj) 调用,取决于它本身是否被 pass_context()

这是一个非常强大的概念,可以用来构建非常复杂的嵌套应用程序; 有关更多信息,复杂的应用程序

无命令下的组调用

默认情况下,除非传递子命令,否则不会调用组命令或多命令。实际上,--help``默认情况下不会自动提供一个命令。 这种行为可以通过传递 ``invoke_without_command=True 给一个组来改变 。在这种情况下,回调总是被调用,而不是显示帮助页面。 上下文对象还包含有关调用是否转到子命令的信息。

举例:

@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    if ctx.invoked_subcommand is None:
        click.echo('I was invoked without subcommand')
    else:
         click.echo('I am about to invoke %s' % ctx.invoked_subcommand)

@cli.command()
def sync():
     click.echo('The subcommand')

它在实践中如何运作:

$ tool
I was invoked without subcommand
$ tool sync
I am about to invoke sync
The subcommand

自定义多命令

除了使用 click.group(), 您还可以建立自己的自定义多命令。当你想要支持从插件中延迟加载的命令时,这很有用。 一个自定义的多命令只需要实现一个列表和加载方法:

import click
import os

plugin_folder = os.path.join(os.path.dirname(__file__), 'commands')

class MyCLI(click.MultiCommand):

    def list_commands(self, ctx):
        rv = []
        for filename in os.listdir(plugin_folder):
            if filename.endswith('.py'):
                rv.append(filename[:-3])
        rv.sort()
        return rv

    def get_command(self, ctx, name):
        ns = {}
        fn = os.path.join(plugin_folder, name + '.py')
        with open(fn) as f:
            code = compile(f.read(), fn, 'exec')
            eval(code, ns, ns)
        return ns['cli']

cli = MyCLI(help='This tool\'s subcommands are loaded from a '
            'plugin folder dynamically.')

if __name__ == '__main__':
    cli()

这些自定义类也可以用于装饰器:

@click.command(cls=MyCLI)
def cli():
    pass

合并多个指令

除了实现自定义多重命令之外,将多个多重命令合并为一个脚本也是有趣的。虽然这个建议通常不如一个嵌套在另一个下面, 但是在某些情况下,合并方法对于更好的外壳体验是有用的。

这种合并系统的默认实现是 CommandCollection 类。它接受其他多个命令的列表,并使命令在同一级别上可用。

用法示例:

import click

@click.group()
def cli1():
    pass

@cli1.command()
def cmd1():
    """Command on cli1"""

@click.group()
def cli2():
    pass

@cli2.command()
def cmd2():
    """Command on cli2"""

cli = click.CommandCollection(sources=[cli1, cli2])

if __name__ == '__main__':
    cli()

它看起来像:

$ cli --help
Usage: cli [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  cmd1  Command on cli1
  cmd2  Command on cli2

如果一个命令存在于多个源中,则第一个源有效。

多命令链接

3.0 新版功能.

有时被允许一次调用多个子命令是有用的。例如,如果您已经安装了setuptools的包,你可能熟悉的前 一个 setup.py sdist bdist_wheel upload 命令链式调用来实现,调用 distbdist_wheel 之前,在 ``upload``之前。从Click 3.0开始,这很容易实现。

你所要做的就是传递 chain=True 给你的多态:

@click.group(chain=True)
def cli():
    pass


@cli.command('sdist')
def sdist():
    click.echo('sdist called')


@cli.command('bdist_wheel')
def bdist_wheel():
    click.echo('bdist_wheel called')

现在你可以像这样调用它:

$ setup.py sdist bdist_wheel
sdist called
bdist_wheel called

当使用多命令链接时,只能在一个参数上使用一个 ``nargs=-1`` 命令(在最后)。在链式多命令 下面嵌套多个命令也是不可能的。除此之外,他们的工作方式没有限制。他们可以正常接受选项和论点。

另外需要注意的是:这个 Context.invoked_subcommand 属性对于多命令来说是没有用处的,它将给 '*' 赋值,如果多个命令调用。这是必要的,因为子命令的处理是一个接一个发生的,所以当回调触发时,将要处理的子命令不可用。

注解

It is currently not possible for chain commands to be nested. This will be fixed in future versions of Click.

多命令管道

3.0新版功能。

多命令链接的一个非常常见的用例是让一个命令处理前一个命令的结果。有多种方式可以促进这一点。最显而易见的方法是在上下文对象上存储一个值,并将其从一个函数处理到另一个函数。这可以通过装饰一个 pass_context() 函数来完成,在这个函数之后提供上下文对象,子命令可以在那里存储它的数据。

另一种方法是通过返回处理函数来设置管线。可以这样想:当一个子命令被调用时,它处理所有的参数,并提出一个如何处理的计划。在那时,它返回一个处理函数并返回。

返回的函数在哪里? 链式多命令可以通过 MultiCommand.resultcallback() 遍历所有这些函数来注册回调,然后调用它们。

为了使这个更具体一些考虑这个例子:

@click.group(chain=True, invoke_without_command=True)
@click.option('-i', '--input', type=click.File('r'))
def cli(input):
    pass

@cli.resultcallback()
def process_pipeline(processors, input):
    iterator = (x.rstrip('\r\n') for x in input)
    for processor in processors:
        iterator = processor(iterator)
    for item in iterator:
        click.echo(item)

@cli.command('uppercase')
def make_uppercase():
    def processor(iterator):
        for line in iterator:
            yield line.upper()
    return processor

@cli.command('lowercase')
def make_lowercase():
    def processor(iterator):
        for line in iterator:
            yield line.lower()
    return processor

@cli.command('strip')
def make_strip():
    def processor(iterator):
        for line in iterator:
            yield line.strip()
    return processor

这是一个很大的问题,所以让我们一步一步来解决。

  1. 首先要做一个可链接的 group() 。 除此之外,即使没有定义子命令,我们也指示单击来调用。如果不这样做,那么调用一个空管道将产生帮助页面,而不是运行结果回调。
  2. 我们接下来要做的就是在我们的小组上注册结果做回调。这个回调将被调用一个参数,该参数是所有子命令的所有返回值的列表,并且是与我们组本身相同的关键字参数。这意味着我们可以轻松访问输入文件,而无需使用上下文对象。
  3. 在这个结果回调中,我们创建了输入文件中所有行的迭代器,然后通过所有从子命令返回的所有回调传入此迭代器,最后我们将所有行打印到stdout。

之后,我们可以根据需要注册许多子命令,每个子命令可以返回一个处理器函数来修改线路流。

需要注意的一个重要的事情是,在每次回调运行之后,Click都会关闭上下文。 这意味着例如文件类型不能在 processor 函数中被访问,因为文件将在那里被关闭。这个限制不太可能改变,因为这会使资源处理变得更加复杂。为此,建议不要使用文件类型,并通过 open_file() 函数打开文件。

对于一个更复杂的例子,在处理管道时也有所改进,请看Click资源库中的 imagepipe multi命令链接演示 <https://github.com/mitsuhiko/click/tree/master/examples/imagepipe> 它实现了一个基于管道的图像编辑工具,具有良好的管道内部结构。

覆盖默认值

默认情况下,参数的默认值是从 default 定义时提供的标志中提取的,但这不是唯一可以从中加载的默认值。另一个地方是 Context.default_map 上下文(字典)。这允许从配置文件加载默认值来覆盖常规的默认值。

如果您插入来自其他软件包的某些命令,但是您对默认值不满意,这很有用。

默认映射可以针对每个子命令任意嵌套,并在脚本被调用时提供。另外,它也可以在任何时候被命令覆盖。例如,顶级命令可以从配置文件加载默认值。

用法示例:

import click

@click.group()
def cli():
    pass

@cli.command()
@click.option('--port', default=8000)
def runserver(port):
    click.echo('Serving on http://127.0.0.1:%d/' % port)

if __name__ == '__main__':
    cli(default_map={
        'runserver': {
            'port': 5000
        }
    })

具体运行如下:

$ cli runserver
Serving on http://127.0.0.1:5000/

上下文默认值

2.0版本新功能。

从Click 2.0开始,不仅可以在调用脚本时覆盖上下文的默认值,还可以在声明命令的装饰器中覆盖默认值。举个例子,前面定义了一个自定义的例子, ``default_map`` 现在也可以在装饰器中完成。

这个例子和前面的例子一样:

import click

CONTEXT_SETTINGS = dict(
    default_map={'runserver': {'port': 5000}}
)

@click.group(context_settings=CONTEXT_SETTINGS)
def cli():
    pass

@cli.command()
@click.option('--port', default=8000)
def runserver(port):
    click.echo('Serving on http://127.0.0.1:%d/' % port)

if __name__ == '__main__':
    cli()

再次举例说明:

$ cli runserver
Serving on http://127.0.0.1:5000/

命令返回值

3.0版本新功能

Click 3.0中的新增功能之一就是完全支持命令回调的返回值。这实现了以前难以实现的全部功能。

实质上,任何命令回调现在都可以返回一个值。这个返回值冒泡给某些接收者。其中一个用例已经在 多命令链接 的例子中显示出来,在这个例子中,链接的多命令可以有处理所有返回值的回调。

在Click中使用命令返回值时,这是你需要知道的:

  • 命令回调的返回值通常从 BaseCommand.invoke() 方法返回 。 这个规则的例外与 Groups:
    • 在一个组中,返回值通常是被调用的子命令的返回值。这个规则的唯一例外是返回值是组的回调的返回值,如果它被调用没有参数和 invoke_without_command 被启用。
    • 如果一个组被设置为链接,则返回值是所有子命令结果的列表。
    • 组的返回值可以通过 MultiCommand.result_callback 来处理。 这是通过链表模式中的所有返回值的列表来调用的,或者是在非链接命令的情况下的单个返回值。
  • 返回值通过 Context.invoke() 方法和 Context.forward() 方法以冒泡的形式返回。这在您内部需要调用另一个命令的情况下非常有用。
  • 点击对返回值没有任何硬性要求,并且不使用它们本身。这允许返回值用于自定义装饰器或工作流(如在多命令链接示例中)。
  • 当Click脚本作为命令行应用程序(通过 BaseCommand.main() ) 被调用时, 除非 standalone_mode 被禁用,否则返回值被忽略 。

用户输入提示

Click 支持两个不同地方的提示。第一种是参数处理发生时自动提示,第二种是后来单独要求提示。

这可以通过 prompt() 功能实现, 该功能要求根据类型进行有效输入,或者使用 confirm() 功能,并在使用时要求确认的功能(是/否)。

选项提示

选项提示集成到选项界面中。有关更多信息,请参阅 提示 。在内部,它会自动调用 prompt()confirm() 根据需要。

输入提示

要手动要求用户输入,您可以使用该 prompt() 功能。 默认情况下,它接受任何Unicode字符串,但您可以要求任何其他类型。例如,你可以要求一个有效的整数:

value = click.prompt('Please enter a valid integer', type=int)

此外,如果提供默认值,则会自动确定类型。例如,以下将只接受浮点数:

value = click.prompt('Please enter a number', default=42.0)

确认提示

要问一个用户是否想要继续一个动作,这个 confirm() 函数就派上用场了。默认情况下,它以布尔值的形式返回提示的结果:

if click.confirm('Do you want to continue?'):
    click.echo('Well done!')

如果程序没有返回 True ,也可以自动中止程序的执行:

click.confirm('Do you want to continue?', abort=True)

记录脚本

Click 可以很容易地记录你的命令行工具。首先,它会自动为您生成帮助页面。虽然这些目前还不能根据其布局进行自定义,但所有文本都可以更改。

帮助文本

命令和选项接受帮助参数。在命令的情况下,功能的文档字符串是自动使用

简单举例:

@click.command()
@click.option('--count', default=1, help='number of greetings')
@click.argument('name')
def hello(count, name):
    """This script prints hello NAME COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

它看起来像:

$ hello --help
Usage: hello [OPTIONS] NAME

  This script prints hello NAME COUNT times.

Options:
  --count INTEGER  number of greetings
  --help           Show this message and exit.

参数不能用这种方式记录。这是遵循Unix工具的一般惯例,只使用最必要的参数来使用参数,并通过名称来引用它们。

防止重新装包

Click 的默认行为是根据终端的宽度重新包装文本。在某些情况下,这可能会成为一个问题。主要的问题是在显示代码示例时,换行符很重要。

重新包装可以通过添加一个只有 \b 转义标记的行来禁用。此行将从帮助文本中删除,重新包装将被禁用。

例:

@click.command()
def cli():
    """First paragraph.

    This is a very long second paragraph and as you
    can see wrapped very early in the source text
    but will be rewrapped to the terminal width in
    the final output.

    \b
    This is
    a paragraph
    without rewrapping.

    And this is a paragraph
    that will be rewrapped again.
    """

它看起来像:

$ cli --help
Usage: cli [OPTIONS]

  First paragraph.

  This is a very long second paragraph and as you can see wrapped very early
  in the source text but will be rewrapped to the terminal width in the
  final output.

  This is
  a paragraph
  without rewrapping.

  And this is a paragraph that will be rewrapped again.

Options:
  --help  Show this message and exit.

元变量

选项和参数接受 metavar 参数,可以更改在帮助页面中的元变量。默认版本是带有下划线的大写参数名称,但如果需要,可以按不同的方式进行注释。这可以在各个层面进行定制:

@click.command(options_metavar='<options>')
@click.option('--count', default=1, help='number of greetings',
              metavar='<int>')
@click.argument('name', metavar='<name>')
def hello(count, name):
    """This script prints hello <name> <int> times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

举例:

$ hello --help
Usage: hello <options> <name>

  This script prints hello <name> <int> times.

Options:
  --count <int>  number of greetings
  --help         Show this message and exit.

命令的短帮助

对于命令,会生成一个简短的帮助代码片断。默认情况下,它是该命令的帮助消息的第一个句子,除非它太长。这也可以被覆盖:

@click.group()
def cli():
    """A simple command line tool."""

@cli.command('init', short_help='init the repo')
def init():
    """Initializes the repository."""

@cli.command('delete', short_help='delete the repo')
def delete():
    """Deletes the repository."""

它看起来像:

$ repo.py
Usage: repo.py [OPTIONS] COMMAND [ARGS]...

  A simple command line tool.

Options:
  --help  Show this message and exit.

Commands:
  delete  delete the repo
  init    init the repo

帮助参数订制

2.0版本新功能

帮助参数在 Click 中以一种非常特殊的方式实现。与常规参数不同的是,它自动通过点击添加任何命令,并执行自动冲突解决。默认情况下它被调用 --help ,但是这个可以改变。如果一个命令本身实现了一个名字相同的参数,那么默认的帮助参数将停止接受它。有一个上下文设置可以用来覆盖所调用的帮助参数的名称 help_option_names

这个例子改变了默认的参数,用 -h----help 代替 --help

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])

@click.command(context_settings=CONTEXT_SETTINGS)
def cli():
    pass

它看起来像:

$ cli -h
Usage: cli [OPTIONS]

Options:
  -h, --help  Show this message and exit.

复杂的应用程序

Click 旨在帮助创建复杂和简单的 CLI 工具。然而,它设计初衷是将任意系统嵌套在一起。例如,如果你曾经使用 Django,你会意识到它提供了一个命令行实用程序,但是 Celery 也有此功能。在 Django 中使用 Celery 时,这两个工具需要互相交互并进行交叉配置。

在两个独立的 Click 命令行实用程序的理论上,它们可以通过嵌套在另一个内部来解决这个问题。例如,Web 框架也可以加载消息队列框架的命令。

基本概念

要理解这是如何工作的,你需要理解两个概念:上下文和调用约定。

上下文(Contexts)

无论何时执行 Click 命令,Context 都会创建一个对象,用于保存此特定调用的状态。它会记住解析的参数,创建它的命令,需要在函数结束时清理哪些资源,等等。它也可以选择性地保存应用程序定义的对象。

上下文对象构建一个链表,直到它们碰到最上面的一个。每个上下文链接到父上下文。这允许命令在另一个命令之下工作,并在那里存储它自己的信息,而不必担心改变父命令的状态。

因为父数据是可用的,但是,如果需要,可以导航到它。

大多数情况下,你没有看到上下文对象,但是当编写更复杂的应用程序时,它会派上用场。下面我们来看下一个概念。

调用约定(Calling Convention)

当执行 Click 命令回调时,它将所有非隐藏参数作为关键字参数传递。Contexts 显然不存在。但是,回调可以选择通过标记自己来传递给上下文对象 pass_context()

那么如果你不知道它是否应该接收上下文(contexts)你怎么调用一个命令回调? 答案是,上下文本身提供了一个辅助函数(Context.invoke())它可以为你做到这一点。 它接受回调作为第一个参数,然后正确调用该函数。

建立一个 Git 克隆

在这个例子中,我们想要构建一个类似于版本控制系统的命令行工具。像 Git 这样的系统通常会提供一个重载的命令,它已经接受了一些参数和配置,然后有额外的子命令来做其他事情。

根命令

在顶层,我们需要一个可以容纳所有命令的组。在这种情况下,我们使用 click.group() 允许我们在其下面注册其他 Click 命令。

对于这个命令,我们也想接受一些配置我们工具状态的参数:

import os
import click


class Repo(object):
    def __init__(self, home=None, debug=False):
        self.home = os.path.abspath(home or '.')
        self.debug = debug


@click.group()
@click.option('--repo-home', envvar='REPO_HOME', default='.repo')
@click.option('--debug/--no-debug', default=False,
              envvar='REPO_DEBUG')
@click.pass_context
def cli(ctx, repo_home, debug):
    ctx.obj = Repo(repo_home, debug)

让我们来看看其中含义,我们创建一个可以有子命令的组命令。当它被调用时,它将创建一个 Repo 类的实例。它将保持我们的命令行工具的状态。在这种情况下,它只是记住一些参数,但在这一点上它也可以加载配置文件等等。

这个状态对象接着被上下文(contexts)作为 obj 所记住。 这是一个特殊的属性,命令应该记住他们需要传递给他们的孩子。

同时,我们需要标记我们的功能 pass_context(), 否则,上下文对象将会把我们完全隐藏掉。

第一个子命令

让我们添加我们的第一个子命令,克隆命令:

@cli.command()
@click.argument('src')
@click.argument('dest', required=False)
def clone(src, dest):
    pass

所以现在我们有一个克隆命令,但是我们如何获得 repo? 一种方法是使用 pass_context() 函数,这个函数也会让我们的回调函数也获得我们之前 repo 掉的上下文(contexts)。 另一种方法,我可以直接使用 pass_obj() 装饰器,它将只传递存储的对象(在我们的例子中是repo):

@cli.command()
@click.argument('src')
@click.argument('dest', required=False)
@click.pass_obj
def clone(repo, src, dest):
    pass
交错命令

虽然与我们想要构建的特定程序无关,但交错命令对交错系统也有很好的支持。例如,我们的版本控制系统有一个超级酷的插件需要大量的配置,并希望将自己的配置存储为 obj。如果我们再附上另一个命令,我们会突然得到插件配置,而不是我们的repo对象。

解决这个问题的一个显而易见的方法就是在插件中存储一个对 repo 的引用,但是这个命令需要知道它是附在这个插件下面的。

有一个更好的系统,可以利用上下文的链接性建立起来。我们知道,插件上下文链接到创建我们的 repo 的上下文。因此,我们可以开始搜索由上下文存储的对象是 repo 的最后一级。

内置支持由 make_pass_decorator(),它将为我们创建装饰器,以查找对象(内部调用
Context.find_object())。在我们的例子中,我们知道我们要找到最接近的 Repo 对象, 所以让我们为此做一个装饰器:
pass_repo = click.make_pass_decorator(Repo)

如果我们现在使用 pass_repo 而不是 pass_obj,我们将总是得到一个 repo,而不是别的:

@cli.command()
@click.argument('src')
@click.argument('dest', required=False)
@pass_repo
def clone(repo, src, dest):
    pass
保障对象的创建

上面的例子只有在有一个外部命令创建一个 Repo 对象并将其存储在上下文中时才起作用。对于一些更高级的用例,这可能会成为一个问题。make_pass_decorator() 默认的行为是调用 Context.find_object() (帮助定位对象)。如果找不到对象,则会引发错误。另一种行为是使用 Context.ensure_object() (帮助定位对象), 如果找不到它,将会创建一个并将其存储在最内层的上下文中。这种行为也可以利用 make_pass_decorator() 传递 ensure=True 来启用:

pass_repo = click.make_pass_decorator(Repo, ensure=True)

在这种情况下,最里面的上下文获取一个对象,如果它缺少。这可能会取代之前放置的对象。即使外部命令没有运行,命令仍然可执行。为此,对象类型需要有一个不接受参数的构造函数。

因此它单独运行:

@click.command()
@pass_repo
def cp(repo):
    click.echo(repo)

你将看到:

$ cp
<Repo object at 0x7efc59d882d0>

高级模式

除了库本身实现的通用功能之外,还有无数的模式可以通过扩展Click来实现。这节内容可以帮你更好完成信息。

命令别名

许多工具支持命令的别名。例如,你可以配置``git`` 来接受 git ci 取别名为 git commit. 其他工具还支持通过自动缩短别名来自动发现别名。

Click 不支持开箱即用, 但是定制 Group 或任何其他 MultiCommand 来提供这个功能是非常容易的。

正如 custom-multi-commands`解释中那样, 一个multi命令可以提供两种方法: :meth:`~MultiCommand.list_commands 和:meth:~MultiCommand.get_command.
在这种特殊情况下,您只需要覆盖后者,因为你通常不希望枚举帮助页面上的别名,以避免混淆。

下面的例子实现了一个接受命令前缀的子类 Group。 如果有一个命令被调用 push, 它会接受 pus 这个别名(只要它是唯一的):

class AliasedGroup(click.Group):

    def get_command(self, ctx, cmd_name):
        rv = click.Group.get_command(self, ctx, cmd_name)
        if rv is not None:
            return rv
        matches = [x for x in self.list_commands(ctx)
                   if x.startswith(cmd_name)]
        if not matches:
            return None
        elif len(matches) == 1:
            return click.Group.get_command(self, ctx, matches[0])
        ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))

然后可以像这样使用它:

@click.command(cls=AliasedGroup)
def cli():
    pass

@cli.command()
def push():
    pass

@cli.command()
def pop():
    pass

参数修改

参数(选项和参数)被转发到命令回调,正如你所看到的。防止参数传递给回调的一个常见方法是参数的expose_value参数,该参数完全隐藏参数。这样做的方式是 Context 对象具有 params 属性,它是所有参数的字典。 表示字典中的任何东西正在传递给回调。

这可以用来补充附加参数。通常这种模式是不推荐的,但在某些情况下,它可能是有用的。至少可以知道这个系统是这样工作的。

import urllib

def open_url(ctx, param, value):
    if value is not None:
        ctx.params['fp'] = urllib.urlopen(value)
        return value

@click.command()
@click.option('--url', callback=open_url)
def cli(url, fp=None):
    if fp is not None:
        click.echo('%s: %s' % (url, fp.code))

在这种情况下,回调 fp 函数会返回不变的URL,但也会传递第二个值给回调函数。 更值得推荐的是将信息传递给包装器:

import urllib

class URL(object):

    def __init__(self, url, fp):
        self.url = url
        self.fp = fp

def open_url(ctx, param, value):
    if value is not None:
        return URL(value, urllib.urlopen(value))

@click.command()
@click.option('--url', callback=open_url)
def cli(url):
    if url is not None:
        click.echo('%s: %s' % (url.url, url.fp.code))

令牌标准化

2.0 新版功能.

从Click 2.0开始,可以提供用于标准化令牌的函数。令牌是选项名称,选项值或命令值。例如,这可以用来实现不区分大小写的选项。

为了使用这个特性,上下文需要传递一个执行标记规范化的函数。例如,你可以有一个将标记转换为小写的函数:

CONTEXT_SETTINGS = dict(token_normalize_func=lambda x: x.lower())

@click.command(context_settings=CONTEXT_SETTINGS)
@click.option('--name', default='Pete')
def cli(name):
    click.echo('Name: %s' % name)

它如何在命令行上工作:

$ cli --NAME=Pete
Name: Pete

调用其他命令

有时,从另一个命令调用一个命令可能会很有趣。但我们不鼓励用这样的click模式,不过你可以自行尝试下 Context.invoke`和 :func:`Context.forward() 方法.

它们的工作方式类似,但区别在于 Context.invoke() 只是用你提供的参数作为调用者调用另一个命令,而 Context.forward() 填充当前命令的参数。 两者都接受命令作为第一个参数,其他的一切都按照你所期望的那样向前传递。

例如:

cli = click.Group()

@cli.command()
@click.option('--count', default=1)
def test(count):
    click.echo('Count: %d' % count)

@cli.command()
@click.option('--count', default=1)
@click.pass_context
def dist(ctx, count):
    ctx.forward(test)
    ctx.invoke(test, count=42)

呈现的效果:

$ cli dist
Count: 1
Count: 42

回调评估顺序

Click的作用与其他一些命令行解析器有所不同,它试图在调用任何回调函数之前,将程序员定义的参数顺序与用户定义的参数顺序进行协调。

在将复杂模式移植到optparse或其他系统进行点击时,这是一个重要的概念。optparse中的参数回调调用是解析步骤的一部分,而Click中的回调调用是在解析之后发生的。

主要区别在于,在optparse中,回调函数会在原始值被调用的情况下调用,而在Click完成转换后调用Click中的回调函数。

通常,调用的顺序是由用户向脚本提供参数的顺序驱动的; 如果有一个选项被调用,--foo 并且一个选项被调用 --bar 用户调用它 --bar--foo,那么这个回调 bar 将会在这个选项之前 触发 foo.

这里有三个特例不遵守这个规则:

渴望:

一个选项可以设置为“渴望”。在所有非渴望参数之前评估所有渴望的参数,但是又按用户在命令行上提供的顺序来评估。

这对于执行参数输出比如 ``--help``和 ``--version``一样重要 两者都是渴望的参数,但是无论命令行上的第一个参数是什么,都将赢得并退出程序。

重复参数:

如果一个选项或者参数在命令行中被分割成多个地方,比如重复 --exclude foo --include baz --exclude bar -- 回调会根据第一个选项的位置触发。在这种情况下,回调将触发 exclude ,它将通过这两个选项(foo 和``bar``),然后回调 include 只会触发 baz

请注意,即使一个参数不允许多个版本,Click仍然会接受第一个的位置,但是会忽略除最后一个之外的每个值。其原因是通过设置默认值的shell别名来允许可组合性。

缺少参数:
如果在命令行中没有定义参数,回调仍然会触发。这与它在optparse中的工作方式不同,未定义的值不会触发回调。缺少参数在最后触发它们的回调,这使得它们可以默认来自之前参数的值。

大多数情况下,你不必关心这些情况,但了解某些高级案例的工作原理非常重要。

转发未知的选项

在某些情况下,能够接受所有未知选项以进一步手动处理是有趣的。点击一般可以做到的点击4.0,但是它仍有一些局限性。对此的支持是通过一个解析器标志调用的In some situations it is interesting to be able ignore_unknown_options ,它将指示解析器收集所有未知的选项,并将它们放到剩余参数中, 而不是触发解析错误。

可以通过下面两种方式激活:

  1. 更改 Command 属性在custom ignore_unknown_options 子类上启用它。
  2. 更改上下文类I (Context.ignore_unknown_options)上相同名称的属性来启用它。这是通过 context_settings 命令字典改变。

对于大多数情况下,最简单的解决方案是第二个。一旦行为被改变,需要拿起那些剩余的选项(在这点上被认为是参数)。为此,你有两个选择:

  1. 你可以使用 pass_context() 来获取传递的上下文。这只有在除了 allow_extra_args ,否则命令将会中止,并有一个错误,存在剩余的参数。如果使用这个解决方案,额外的参数将被收集在 :attr:`Context.args`中。

2. 你可以附上 argument()nargs 设置为 -1 ,这将吃掉所有剩余参数。 在这种情况下,建议将类型设置为 UNPROCESSED 以避免对这些参数进行任何字符串处理, 否则它们会被自动强制为unicode字符串,这通常不是您想要的。

最后你会得到这样的结果:

import sys
from subprocess import call

@click.command(context_settings=dict(
    ignore_unknown_options=True,
))
@click.option('-v', '--verbose', is_flag=True, help='Enables verbose mode')
@click.argument('timeit_args', nargs=-1, type=click.UNPROCESSED)
def cli(verbose, timeit_args):
    """A wrapper around Python's timeit."""
    cmdline = ['python', '-mtimeit'] + list(timeit_args)
    if verbose:
        click.echo('Invoking: %s' % ' '.join(cmdline))
    call(cmdline)

它看起来像:

$ cli --help
Usage: cli [OPTIONS] [TIMEIT_ARGS]...

  A wrapper around Python's timeit.

Options:
  -v, --verbose  Enables verbose mode
  --help         Show this message and exit.

$ cli -n 100 "a = 1; b = 2; a * b"
100 loops, best of 3: 0.0811 usec per loop

$ cli -v "a = 1; b = 2; a * b"
Invoking: python -mtimeit a = 1; b = 2; a * b
10000000 loops, best of 3: 0.0719 usec per loop

正如你所看到的,通过Click来处理详细性标志,其他的一切都会在timeit_args变量中进行进一步处理,然后调用一个子进程。关于如何忽略未处理的标志,有几件重要的事情要知道:

  • 未知的长选项通常被忽略,根本不处理。因此,举例来说,无论 --foo=bar``还是 ``--foo bar 传递

他们通常最终会这样。请注意,因为解析器无法知道某个选项是否会接受参数,所以 bar 部分可能会作为 参数进行处理。 * 未知的短期选项可能会被部分处理,如有必要可重新调整。例如在上面的例子中,有一个选项 -v 可以启用详细模式。如果该命令将被忽略, -va 那么 -v 部分将由Click处理(因为它是已知的) 并且 -a 将在剩余参数中结束以用于进一步处理。 * 根据你的计划,你可能会通过禁用散布的参数(allow_interspersed_args) 来取得一些成功,它指示解析器不允许混合参数和选项。根据你的情况,这可能会改善你的结果。

一般来说,虽然从你自己的命令和来自另一个应用程序的命令的选项和参数的组合处理是不鼓励的,请尽可能避免这种情况。将子命令下的所有内容都转发给另一个应用程序比自己处理一些参数更好。

全局上下文访问

5.0 新版功能.

从Click 5.0开始,可以通过使用:func:get_current_context 函数从同一个线程中的任何地方访问当前上下 文,这主要用于访问上下文绑定对象以及存储在其上的一些标志,以定制运行时行为。例如 echo() 函数可以用来推断颜色标志的默认值。

用法示例:

def get_current_command_name():
    return click.get_current_context().info_name

应该指出的是,这只适用于当前线程。如果你产生了额外的线程,那么这些线程将无法引用当前上下文。如果你想给另一个线程引用这个上下文的能力,你需要使用线程内的上下文作为上下文管理器:

def spawn_thread(ctx, func):
    def wrapper():
        with ctx:
            func()
    t = threading.Thread(target=wrapper)
    t.start()
    return t

现在线程函数可以像主线程那样访问上下文。但是,如果你使用线程的话,你需要非常小心,因为绝大多数的上下文不是线程安全的!你只能从上下文中读取,而不能对其进行任何修改。

测试 Click 程序

对于基础的测试,Click 提供了 click.testing 模块,它可以调用命令行程序然后检测它的功能。

这类工具真的只能用于测试,因为为了实现简单它们会更改整个解释器的状态,而且不是线程安全的。

基础测试

CliRunner 是测试 Click 程序最基础的功能,它能够调用命令作为命令行脚本。 CliRunner.invoke() 方法可以隔离环境中运行命令行脚本并以字节和二进制格式捕获输出数据。

返回结果是一个 Result 对象,它可以捕获输出数据,退出代码,附加可选异常。

例如:

import click
from click.testing import CliRunner

def test_hello_world():
    @click.command()
    @click.argument('name')
    def hello(name):
        click.echo('Hello %s!' % name)

    runner = CliRunner()
    result = runner.invoke(hello, ['Peter'])
    assert result.exit_code == 0
    assert result.output == 'Hello Peter!\n'

对于子命令测试,子命令的名称必须在 CliRunner.invoke() 方法 args 中的指定。

例如:

import click
from click.testing import CliRunner

def test_sync():
    @click.group()
    @click.option('--debug/--no-debug', default=False)
    def cli(debug):
        click.echo('Debug mode is %s' % ('on' if debug else 'off'))

    @cli.command()
    def sync():
        click.echo('Syncing')

    runner = CliRunner()
    result = runner.invoke(cli, ['--debug', 'sync'])
    assert result.exit_code == 0
    assert 'Debug mode is on' in result.output
    assert 'Syncing' in result.output

文件系统隔离

对于基础的想要使用文件系统的命令行工具。CliRunner.isolated_filesystem() 方法将非常有用,它会创建一个空的文件夹,并将当前路径设置为空文件夹的路径。

例如:

import click
from click.testing import CliRunner

def test_cat():
    @click.command()
    @click.argument('f', type=click.File())
    def cat(f):
        click.echo(f.read())

    runner = CliRunner()
    with runner.isolated_filesystem():
        with open('hello.txt', 'w') as f:
            f.write('Hello World!')

        result = runner.invoke(cat, ['hello.txt'])
        assert result.exit_code == 0
        assert result.output == 'Hello World!\n'

输入流

测试装饰器也可以用来为输入流(stdin)提供输入数据。这在测试提示时会非常有用,比如:

import click
from click.testing import CliRunner

def test_prompts():
    @click.command()
    @click.option('--foo', prompt=True)
    def test(foo):
        click.echo('foo=%s' % foo)

    runner = CliRunner()
    result = runner.invoke(test, input='wau wau\n')
    assert not result.exception
    assert result.output == 'Foo: wau wau\nfoo=wau wau\n'

注意:因为提示是模拟的,所以写入输入数据和输出数据也是模拟的。如果预计会被隐藏的输入那么显然结果不会发生。

实用工具

除了 Click 提供的与参数解析和处理接口的功能之外,它还提供了一些附加功能,对编写命令行实用程序非常有用。

打印标准输出

最明显的帮助是 echo() 函数,它在很多方面像 Python 的 print 句或函数一样工作。主要区别在于它在Python 2和Python 3中的工作原理是相同的,它智能地检测错误配置的输出流,并且永远不会出错 (Python 3除外;更多信息请参阅 Python 3 的限制)。

举例:

import click

click.echo('Hello World!')

最重要的是,它可以打印Unicode和二进制数据,不像在Python 3中的内置函数 print ,它不能输出任何字节。但是,它会默认发出一个尾随的换行符,这需要通过传递 nl=False:

click.echo(b'\xe2\x98\x83', nl=False)

最后但并非最不重要的一点,就是 echo() 使用click的智能内部输出流来支持在Windows控制台上支持unicode输出的stdout和stderr。 这意味着只要你使用的是 click.echo 你可以输出unicode字符(对于哪些字符可以显示,在默认字体上有一些限制)。该功能在 Click 6.0中是新功能。

6.0 新版功能.

现在单击模拟Windows上的输出流,以通过单独的API支持到Windows控制台的unicode。欲了解更多信息,请参阅 `wincmd`_

3.0 新版功能.

从Click 3.0开始,您也可以通过传递 err=True ,以下内容轻松地打印到标准错误:

click.echo('Hello World!', err=True)

ANSI颜色

2.0 新版功能.

从Click 2.0开始,该 echo() 函数获得了处理ANSI颜色和样式的额外功能。 在Windows上,此功能仅在安装了 colorama 时可用。如果安装,则ANSI代码将被智能处理。

这主要意味着:

  • Click 的 echo() 函数功能,如果流没有连接到终端,会自动剥离ANSI颜色代码。
  • echo() 功能将透明地连接到Windows上的终端,并将ANSI代码翻译成终端API调用。这意味着颜色在Windows上的工作方式与其他操作系统上的相同。

关于 colorama 支持的注意事项:将自动检测何时 可用色彩并使用它。难道 colorama.init()!

要安装 colorama, 请运行以下命令:

$ pip install colorama

对于字符串的样式, style() 函数可以如下使用:

import click

click.echo(click.style('Hello World!', fg='green'))
click.echo(click.style('Some more text', bg='blue', fg='white'))
click.echo(click.style('ATTENTION', blink=True, bold=True))

关于 echo() 函数和 style() 函数也称为单一功能,可用 secho() 函数:

click.secho('Hello World!', fg='green')
click.secho('Some more text', bg='blue', fg='white')
click.secho('ATTENTION', blink=True, bold=True)

分页支持

在某些情况下,您可能希望在终端上显示长文本,并让用户滚动浏览。这可以通过使用与 echo_via_pager() 函数类似的 echo() 函数来实现 ,但是总是写入标准输出,如果可能的话,可以使用分页器。

举例:

@click.command()
def less():
    click.echo_via_pager('\n'.join('Line %d' % idx
                                    for idx in range(200)))

屏幕清除

2.0 新版功能.

要清除终端屏幕,您可以使用 clear() 从Click 2.0开始提供的功能。它的名字的确如此:它以平台不可知的方式清除整个可见的屏幕:

import click
click.clear()

从终端获取字符

2.0 新版功能.

通常,当从终端读取输入时,您将从标准输入读取。但是,这是缓冲输入,直到线路终止才显示。在某些情况下,您可能不想这样做,而是在写入时读取单个字符。

为此,Click提供了 getchar() 函数,从终端缓冲区读取单个字符并将其作为Unicode字符返回的功能。

请注意,即使标准输入是管道,此功能也将始终从终端读取。

举例:

 import click

click.echo('Continue? [yn] ', nl=False)
c = click.getchar()
click.echo()
if c == 'y':
    click.echo('We will go on')
elif c == 'n':
    click.echo('Abort!')
else:
    click.echo('Invalid input :(')

请注意,这读取原始输入,这意味着像箭头键的东西将出现在平台的本机转义格式。翻译的字符只有 ^C^D 其分别转换成键盘中断和异常的文件结束。这样做是因为否则,忘记这一点太容易了,并且创建不能正确退出的脚本。

等待键入信号

2.0 新版功能.

有时,暂停直到用户按下键盘上的任何键都是有用的。这在Windows cmd.exe 上将特别有用,默认情况下会在命令执行结束时关闭窗口,而不是等待。

在点击中,这可以通过该 pause() 功能来完成。此功能将打印一个快捷的信息给终端(可以自定义),并等待用户按下一个键。除此之外,如果脚本没有交互运行,它也会成为NOP(无操作指令)。

举例:

import click
click.pause()

启动编辑

2.0 新版功能.

Click 支持自动启动编辑器 edit() 。这对询问用户多行输入非常有用。它会自动打开用户定义的编辑器或回退到合理的默认值。如果用户关闭编辑器而不保存,则返回值将是None,否则为输入的文本。

用法示例:

import click

def get_commit_message():
    MARKER = '# Everything below is ignored\n'
    message = click.edit('\n\n' + MARKER)
    if message is not None:
        return message.split(MARKER, 1)[0].rstrip('\n')

或者,也可以使用该功能通过特定文件名启动文件的编辑器。在这种情况下,返回值总是为 None

举例:

import click
click.edit(filename='/etc/passwd')

启动应用程序

2.0 新版功能.

Click 支持通过启动应用程序 launch(). 可以用来打开与URL或文件类型关联的默认应用程序。例如,这可用于启动Web浏览器或图片浏览器。除此之外,它还可以启动文件管理器并自动选择提供的文件。

用法示例:

click.launch('http://click.pocoo.org/')
click.launch('/my/downloaded/file.txt', locate=True)

打印文件名

由于文件名可能不是Unicode,格式化它们可能有点棘手。通常,在Python 2中比在3上更容易,因为你可以用这个 print 函数把字节写到stdout中,但是在Python 3中,你总是需要使用Unicode。

这与点击工作的方式是通过 format_filename() 它尽最大努力将文件名转换为Unicode,永远不会失败。这使得可以在完整的Unicode字符串的上下文中使用这些文件名。

举例:

click.echo('Path: %s' % click.format_filename(b'foo.txt'))

标准流

对于命令行工具来说,可靠地访问输入输出流是非常重要的。Python通常提供通过 sys.stdout , 和友元方法访问这些流,但不幸的是,在2.x和3.x之间有API差异,特别是关于这些流如何响应Unicode和二进制数据。

正因为如此,click提供了 get_binary_stream()get_text_stream() 函数,这些函数可以在不同的Python版本以及各种各样的pf终端配置下产生一致的结果。

最终的结果是,这些函数将总是返回一个功能流对象(除非在Python 3中很奇怪的情况;请参阅 Python 3 的限制).

举例:

import click

stdin_text = click.get_text_stream('stdin')
stdout_binary = click.get_binary_stream('stdout')

6.0 新版功能.

现在 Click 模拟Windows上的输出流,以通过单独的API支持到Windows控制台的unicode。欲了解更多信息,请参阅 `wincmd`_.

智能文件打开

3.0 新版功能.

从Click 3.0开始, File 通过 open_file() 函数公开从文件中打开文件的逻辑。它可以智能地打开标准输入/标准输出以及任何其他文件。

举例:

import click

stdout = click.open_file('-', 'w')
test_file = click.open_file('test.txt', 'w')

如果返回stdin或stdout,则返回值被封装在一个特殊的文件中,上下文管理器将阻止文件的关闭。这使得标准流的处理是透明的,你可以像这样使用它:

with click.open_file(filename, 'w') as f:
    f.write('Hello World!\n')

查找应用程序文件夹

2.0 新版功能.

Very often, you want to open a configuration file that belongs to your application. However, different operating systems store these configuration files in different locations depending on their standards. Click provides a get_app_dir() function which returns the most appropriate location for per-user config files for your application depending on the OS.

Example usage:

import os
import click
import ConfigParser

APP_NAME = 'My Application'

def read_config():
    cfg = os.path.join(click.get_app_dir(APP_NAME), 'config.ini')
    parser = ConfigParser.RawConfigParser()
    parser.read([cfg])
    rv = {}
    for section in parser.sections():
        for key, value in parser.items(section):
            rv['%s.%s' % (section, key)] = value
    return rv

显示进度条

2.0 新版功能.

有时候,你有命令行脚本需要处理大量的数据,但是你想要快速地向用户展示一下这个过程需要多长时间。点击支持通过该 progressbar() 函数进行简单的进度条渲染。

基本用法非常简单:这个想法是你有一个你想要操作的迭代器。对于迭代中的每个项目,可能需要一些时间来处理。所以说你有这样一个循环:

for user in all_the_users_to_process:
    modify_the_user(user)

要连接一个自动更新的进度条,只需要将代码更改为:

import click

with click.progressbar(all_the_users_to_process) as bar:
    for user in bar:
        modify_the_user(user)

Click 会自动将进度条打印到终端,并计算剩余的时间。剩余时间的计算要求可迭代的长度。如果它没有长度,但你知道长度,你可以明确地提供它:

with click.progressbar(all_the_users_to_process,
                       length=number_of_users) as bar:
    for user in bar:
        modify_the_user(user)

另一个有用的功能是将标签与将在进度条之前显示的进度条相关联:

with click.progressbar(all_the_users_to_process,
                       label='Modifying user accounts',
                       length=number_of_users) as bar:
    for user in bar:
        modify_the_user(user)

有时,可能需要迭代外部迭代器,并不规则地前进进度条。为此,您需要指定长度(并且不可迭代),并在上下文返回值上使用update方法,而不是直接在其上进行迭代:

with click.progressbar(length=total_size,
                       label='Unzipping archive') as bar:
    for archive in zip_file:
        archive.extract()
        bar.update(archive.size)

Bash 参数补全

2.0 新版功能.

Click 2.0 中的任何 Click 脚本都支持 Bash 参数补全。在完成这项工作时,会有一些限制,但大多数情况下,它是可以正常工作的。

限制

只有当脚本正确安装时,才可以使用 Bash 参数补全,而不是通过 python 命令执行。 如何做到这一点,参见 Setuptools 集成。此外,Click 目前只支持 Bash 参数补全。

目前,Bash 参数补全是一个无法修改的内部特性。可能未来的版本会有更多的选择。

它能补全什么

一般,Bash 参数补全支持补全子命令和参数。子命令随时都可以被补全出来,而参数只有在提供一个 - 符号后才可以进行补全。比如:

$ repo <TAB><TAB>
clone    commit   copy     delete   setuser
$ repo clone -<TAB><TAB>
--deep     --help     --rev      --shallow  -r

激活

为了激活 Bash 补全功能,你需要通知 Bash 你的脚本可以使用补全和如何使用补全。任何 Click 程序都会自动完成这个工作。 一般情况下这项功能通过一个神奇的环境变量 _<PROG_NAME>_COMPLETE 来工作,其中 <PROG_NAME> 是你的以 _ 分割的大写的可执行程序的名称。

如果你的工具叫做 foo-bar, 那么这个神奇的变量应该叫做 _FOO_BAR_COMPLETE。通过使用 source 将工具名导出,它将吐出可以被激活的激活脚本。

比如说,为 foo-bar 脚本开启 Bash 补全功能,你需要将下列命令放入到 .bashrc:

eval "$(_FOO_BAR_COMPLETE=source foo-bar)"

从此以后,你的脚本将启用 Bash 补全功能。

激活脚本

上述的激活示例总是在启动时调用你的应用程序。如果你有很多的此类应用程序这将会大大增加你的 shell 记过时间。另一个选择是你可以将上述生成的内容通过 一个文件发送,这也是 Git 和其他系统正在做的事情。

通过下列方式简单地实现:

_FOO_BAR_COMPLETE=source foo-bar > foo-bar-complete.sh

然后将下列命令放入你的 bashrc 中取代之前的命令:

. /path/to/foo-bar-complete.sh

异常处理

Click内部使用异常提示来表示应用程序的用户设置的各种错误条件。这是使用不当所造成的。

错误在哪里处理?

Click的主要错误处理发生在 BaseCommand.main(). 在那里它处理所有的子类 ClickException 以及 EOFErrorKeyboardInterrupt 标准。后者在内部翻译成一个 Abort.

应用的逻辑如下:

  1. 如果 EOFError 或者 KeyboardInterrupt 发生,,将其重新评估为 Abort.
  2. 如果出现一个 ClickException , 调用 ClickException.show() 方法来显示它,然后退出程序 ClickException.exit_code.
  3. 如果发生 Abort 异常,则将字符串打印Aborted! 到标准错误,并使用退出代码退出程序1。
  4. 如果顺利通过,退出程序退出代码0。

如果我不想要呢?

一般来说,你总是可以选择自己调用 invoke() 方法。例如,如果你有一个

Command 你可以像这样手动调用它:

ctx = command.make_context('command-name', ['args', 'go', 'here'])
with ctx:
    result = command.invoke(ctx)

在这种情况下,异常将不会被完全处理,并且会像你期望的那样冒出来。

从Click 3.0开始,你也可以使用该 Command.main() 方法,但禁用独立模式将执行两项操作:禁用异常处理并在最后通过 sys.exit() 禁用隐式模式。

所以你可以这样做::

command.main(['command-name', 'args', 'go', 'here'],
             standalone_mode=False)

存在哪些例外?

Click 具有两个异常基础: ClickException 针对所有例外情况引发的Click,这些异常是要向用户发出信号,而 Abort 用于指示Click的中止执行。

ClickException 有一个 show() 方法可以将错误消息呈现给stderr或给定的文件对象。如果你想自己使用这个异常做一些检查他们提供的API文档。

以下常见存在的子类:

  • UsageError 通知用户出了问题。
  • BadParameter 通知用户特定参数出现问题。这些通常在Click处理内部处理,如果可能的话,增加额外的信息。例如,如果这些是从回调引发Click,将自动增加它的参数名称。
  • FileError 这是一个错误, FileType Click遇到打开文件问题时会出现

Python 3 支持

Click 支持Python 3,但像所有其他命令行实用程序库一样,它受到 Python 3 中的 Unicode 文本模型的影响。文档中的所有示例都是为了能够在Python 2.x和Python 3.3或更高版本上运行而编写的。

目前,强烈建议使用 Python 2 作为 Click 实用程序,除非 Python 3 是一个硬性要求。

Python 3 的限制

目前, Clik Python 3中的几个问题:

  • Unix中的命令行传统上是以字节为单位的,而不是Unicode。虽然有编码暗示所有这一切,通常有一些情况下,可以打破。最常见的是SSH连接到不同语言环境的机器。

由于缺少对双向代用转义的支持,错误配置的环境目前可能导致Python 3中的各种Unicode问题。这不会在Click中修复!

有关更多信息,请参阅 Python 3 代理处理.

  • Python 3中的标准输入和输出默认以Unicode模式打开。在某些情况下,Click 必须以二进制模式重新打开流。因为没有标准化的方式来做到这一点,所以这可能并不总是奏效。主要是在测试命令行应用程序时,这可能会成为问题。

    这不支持:

     sys.stdin = io.S tringIO('Input here')
    sys.stdout = io.StringIO()
    

    你需要这样做:

     input = 'Input  here'
    in_stream = io.BytesIO(input.encode('utf-8'))
    sys.stdin = io.TextIOWrapper(in_stream, encoding='utf-8')
    out_stream = io.BytesIO()
    sys.stdout = io.TextIOWrapper(out_stream, encoding='utf-8')
    

请记住,在这种情况下,你需要使用 out_stream.getvalue() 而不是 sys.stdout.getvalue() 如果你想访问缓冲区的内容,因为包装将不会转发该方法。

Python 2 和 3 的差异

通过遵循两种版本的最佳做法,Click 尝试最小化缩减Python 2和Python 3之间的差异。

在Python 2中,以下是正确的:

  • sys.stdin, sys.stdout, 和 sys.stderr 以二进制模式打开,但在某些情况下,它们支持Unicode输出。单击尝试不能颠覆这一点,但提供支持强制流是基于Unicode的。
  • sys.argv 总是以字节为基础的。Click将字节传递给所有输入类型,并根据需要进行转换。 The STRING 类型自动将正确解码输入值插入尝试最合适的编码字符串。
  • 处理文件时,Click将永远不会通过Unicode API,而是使用操作系统的字节API来打开文件。

在Python 3中,以下是正确的:

  • sys.stdin, sys.stdoutsys.stderr 默认情况下是基于文本的。当Click需要二进制流时,它会尝试发现基础二进制流。请参阅 Python 3 的限制 以了解其工作原理。

  • sys.argv 始终是基于Unicode的。这也意味着Click中类型的输入值的本机类型是Unicode,而不是字节。

    这会导致问题,如果终端设置不正确,Python不会计算出编码。在这种情况下,Unicode字符串将包含编码为代理转义的错误字节。

  • 处理文件时,Click将始终使用Unicode文件系统API调用,方法是使用操作系统的报告或猜测的文件系统编码。代理支持文件名,因此应该可以通过 File 类型打开文件,即使环境配置错误也是如此。

Python 3 代理处理

在Python 3中单击将执行标准库中的所有Unicode处理,并受其行为影响。在Python 2中,Click单独处理所有的Unicode,这意味着在错误行为上存在差异。

最明显的区别是,在Python 2中,Unicode将“正常工作”,而在Python 3中,它需要特别小心。原因是在Python 3中,编码检测是在解释器中完成的,在Linux和某些其他操作系统上,其编码处理是有问题的。

最大的难题来源是init系统(sysvinit,upstart,systemd等),部署工具(salt,puppet)或cron作业(cron)调用的Click脚本将拒绝工作,除非导出Unicode区域设置。

如果Click遇到这样的环境,它将阻止进一步的执行,迫使你设置一个语言环境。这样做是因为一旦被调用,Click不知道系统的状态,并在Python的Unicode处理加入之前恢复值。

如果你在Python 3中看到这样的错误:

Traceback (most recent call last):
  ...
RuntimeError: Click will abort further execution because Python 3 was
  configured to use ASCII as encoding for the environment. Either switch
  to Python 2 or consult http://click.pocoo.org/python3/ for
  mitigation steps.

您正在处理Python 3认为您仅限于ASCII数据的环境。这些问题的解决方案取决于您的计算机运行在哪个区域。

例如,如果你有一台德语的Linux机器,你可以通过导出语言环境来解决这个问题 de_DE.utf-8:

export LC_ALL=de_DE. utf-8
export LANG=de_DE.utf-8

如果你在US机器上, 选择的是 en_US.utf-8 编码。在一些较新的Linux系统上,你也可以尝试一下 C.UTF-8 作为本地编码:

export LC_ALL=C.UTF-8
export LANG=C.UTF-8

在某些系统上,据报道, UTF-8 必须写成 UTF8 ,反之亦然。要查看哪些语言环境支持,您可以调用 locale -a:

locale -a

您需要在调用Python脚本之前执行此操作。如果你对这个原因感到好奇,你可以参加Python 3 bug跟踪器的讨论:

Unicode 常量

从Click 5.0开始,将会在Python 2中使用未来导入 unicode_literals 警告。This has been done due to 这是由于导入导致的负面影响而导致的,这是由于将Unicode数据引入到无法处理的API而导致的无意中导致的错误他们。对于这个问题的一些例子,请参阅关于这个github问题的讨论: python-future#22.

如果您 unicode_literals 在任何定义Click命令的文件中使用或者调用了单击命令,将会给您一个警告。强烈建议您不要使用 Unicode 字符串的 unicode_literals 明确 u 前缀。

如果您想忽略警告并继续使用 unicode_literals 自己的危险,可以按如下所示禁用警告:

import click
click.disable_unicode_literals_warning = True

Windows Console Notes

6.0 新版功能.

Until Click 6.0 there are various bugs and limitations with using Click on a Windows console. Most notably the decoding of command line arguments was performed with the wrong encoding on Python 2 and on all versions of Python output of unicode characters was impossible. Starting with Click 6.0 we now emulate output streams on Windows to support unicode to the Windows console through separate APIs and we perform different decoding of parameters.

Here is a brief overview of how this works and what it means to you.

Unicode Arguments

Click internally is generally based on the concept that any argument can come in as either byte string or unicode string and conversion is performed to the type expected value as late as possible. This has some advantages as it allows us to accept the data in the most appropriate form for the operating system and Python version.

For instance paths are left as bytes on Python 2 unless you explicitly tell it otherwise.

This caused some problems on Windows where initially the wrong encoding was used and garbage ended up in your input data. We not only fixed the encoding part, but we also now extract unicode parameters from sys.argv.

This means that on Python 2 under Windows, the arguments processed will most likely be of unicode nature and not bytes. This was something that previously did not really happen unless you explicitly passed in unicode parameters so your custom types need to be aware of this.

There is also another limitation with this: if sys.argv was modified prior to invoking a click handler, we have to fall back to the regular byte input in which case not all unicode values are available but only a subset of the codepage used for parameters.

Unicode Output and Input

Unicode output and input on Windows is implemented through the concept of a dispatching text stream. What this means is that when click first needs a text output (or input) stream on windows it goes through a few checks to figure out of a windows console is connected or not. If no Windows console is present then the text output stream is returned as such and the encoding for that stream is set to utf-8 like on all platforms.

However if a console is connected the stream will instead be emulated and use the cmd.exe unicode APIs to output text information. In this case the stream will also use utf-16-le as internal encoding. However there is some hackery going on that the underlying raw IO buffer is still bypassing the unicode APIs and byte output through an indirection is still possible.

This hackery is used on both Python 2 and Python 3 as neither version of Python has native support for cmd.exe with unicode characters. There are some limitations you need to be aware of:

  • this unicode support is limited to click.echo, click.prompt as well as click.get_text_stream.
  • depending on if unicode values or byte strings are passed the control flow goes completely different places internally which can have some odd artifacts if data partially ends up being buffered. Click attempts to protect against that by manually always flushing but if you are mixing and matching different string types to stdout or stderr you will need to manually flush.

Another important thing to note is that the Windows console's default fonts do not support a lot of characters which means that you are mostly limited to international letters but no emojis or special characters.

API Reference

如果你想查阅一个特定函数、类或者方法的具体信息,请查阅这部分文档。

API

This part of the documentation lists the full API reference of all public classes and functions.

Decorators

click.command(name=None, cls=None, **attrs)

Creates a new Command and uses the decorated function as callback. This will also automatically attach all decorated option()s and argument()s as parameters to the command.

The name of the command defaults to the name of the function. If you want to change that, you can pass the intended name as the first argument.

All keyword arguments are forwarded to the underlying command class.

Once decorated the function turns into a Command instance that can be invoked as a command line utility or be attached to a command Group.

参数:
  • name -- the name of the command. This defaults to the function name.
  • cls -- the command class to instantiate. This defaults to Command.
click.group(name=None, **attrs)

Creates a new Group with a function as callback. This works otherwise the same as command() just that the cls parameter is set to Group.

click.argument(*param_decls, **attrs)

Attaches an argument to the command. All positional arguments are passed as parameter declarations to Argument; all keyword arguments are forwarded unchanged (except cls). This is equivalent to creating an Argument instance manually and attaching it to the Command.params list.

参数:cls -- the argument class to instantiate. This defaults to Argument.
click.option(*param_decls, **attrs)

Attaches an option to the command. All positional arguments are passed as parameter declarations to Option; all keyword arguments are forwarded unchanged (except cls). This is equivalent to creating an Option instance manually and attaching it to the Command.params list.

参数:cls -- the option class to instantiate. This defaults to Option.
click.password_option(*param_decls, **attrs)

Shortcut for password prompts.

This is equivalent to decorating a function with option() with the following parameters:

@click.command()
@click.option('--password', prompt=True, confirmation_prompt=True,
              hide_input=True)
def changeadmin(password):
    pass
click.confirmation_option(*param_decls, **attrs)

Shortcut for confirmation prompts that can be ignored by passing --yes as parameter.

This is equivalent to decorating a function with option() with the following parameters:

def callback(ctx, param, value):
    if not value:
        ctx.abort()

@click.command()
@click.option('--yes', is_flag=True, callback=callback,
              expose_value=False, prompt='Do you want to continue?')
def dropdb():
    pass
click.version_option(version=None, *param_decls, **attrs)

Adds a --version option which immediately ends the program printing out the version number. This is implemented as an eager option that prints the version and exits the program in the callback.

参数:
  • version -- the version number to show. If not provided Click attempts an auto discovery via setuptools.
  • prog_name -- the name of the program (defaults to autodetection)
  • message -- custom message to show instead of the default ('%(prog)s, version %(version)s')
  • others -- everything else is forwarded to option().
click.help_option(*param_decls, **attrs)

Adds a --help option which immediately ends the program printing out the help page. This is usually unnecessary to add as this is added by default to all commands unless suppressed.

Like version_option(), this is implemented as eager option that prints in the callback and exits.

All arguments are forwarded to option().

click.pass_context(f)

Marks a callback as wanting to receive the current context object as first argument.

click.pass_obj(f)

Similar to pass_context(), but only pass the object on the context onwards (Context.obj). This is useful if that object represents the state of a nested system.

click.make_pass_decorator(object_type, ensure=False)

Given an object type this creates a decorator that will work similar to pass_obj() but instead of passing the object of the current context, it will find the innermost context of type object_type().

This generates a decorator that works roughly like this:

from functools import update_wrapper

def decorator(f):
    @pass_context
    def new_func(ctx, *args, **kwargs):
        obj = ctx.find_object(object_type)
        return ctx.invoke(f, obj, *args, **kwargs)
    return update_wrapper(new_func, f)
return decorator
参数:
  • object_type -- the type of the object to pass.
  • ensure -- if set to True, a new object will be created and remembered on the context if it's not there yet.

Utilities

click.echo(message=None, file=None, nl=True, err=False, color=None)

Prints a message plus a newline to the given file or stdout. On first sight, this looks like the print function, but it has improved support for handling Unicode and binary data that does not fail no matter how badly configured the system is.

Primarily it means that you can print binary data as well as Unicode data on both 2.x and 3.x to the given file in the most appropriate way possible. This is a very carefree function as in that it will try its best to not fail. As of Click 6.0 this includes support for unicode output on the Windows console.

In addition to that, if colorama is installed, the echo function will also support clever handling of ANSI codes. Essentially it will then do the following:

  • add transparent handling of ANSI color codes on Windows.
  • hide ANSI codes automatically if the destination file is not a terminal.

在 6.0 版更改: As of Click 6.0 the echo function will properly support unicode output on the windows console. Not that click does not modify the interpreter in any way which means that sys.stdout or the print statement or function will still not provide unicode support.

在 2.0 版更改: Starting with version 2.0 of Click, the echo function will work with colorama if it's installed.

3.0 新版功能: The err parameter was added.

在 4.0 版更改: Added the color flag.

参数:
  • message -- the message to print
  • file -- the file to write to (defaults to stdout)
  • err -- if set to true the file defaults to stderr instead of stdout. This is faster and easier than calling get_text_stderr() yourself.
  • nl -- if set to True (the default) a newline is printed afterwards.
  • color -- controls if the terminal supports ANSI colors or not. The default is autodetection.
click.echo_via_pager(text, color=None)

This function takes a text and shows it via an environment specific pager on stdout.

在 3.0 版更改: Added the color flag.

参数:
  • text -- the text to page.
  • color -- controls if the pager supports ANSI colors or not. The default is autodetection.
click.prompt(text, default=None, hide_input=False, confirmation_prompt=False, type=None, value_proc=None, prompt_suffix=': ', show_default=True, err=False)

Prompts a user for input. This is a convenience function that can be used to prompt a user for input later.

If the user aborts the input by sending a interrupt signal, this function will catch it and raise a Abort exception.

6.0 新版功能: Added unicode support for cmd.exe on Windows.

4.0 新版功能: Added the err parameter.

参数:
  • text -- the text to show for the prompt.
  • default -- the default value to use if no input happens. If this is not given it will prompt until it's aborted.
  • hide_input -- if this is set to true then the input value will be hidden.
  • confirmation_prompt -- asks for confirmation for the value.
  • type -- the type to use to check the value against.
  • value_proc -- if this parameter is provided it's a function that is invoked instead of the type conversion to convert a value.
  • prompt_suffix -- a suffix that should be added to the prompt.
  • show_default -- shows or hides the default value in the prompt.
  • err -- if set to true the file defaults to stderr instead of stdout, the same as with echo.
click.confirm(text, default=False, abort=False, prompt_suffix=': ', show_default=True, err=False)

Prompts for confirmation (yes/no question).

If the user aborts the input by sending a interrupt signal this function will catch it and raise a Abort exception.

4.0 新版功能: Added the err parameter.

参数:
  • text -- the question to ask.
  • default -- the default for the prompt.
  • abort -- if this is set to True a negative answer aborts the exception by raising Abort.
  • prompt_suffix -- a suffix that should be added to the prompt.
  • show_default -- shows or hides the default value in the prompt.
  • err -- if set to true the file defaults to stderr instead of stdout, the same as with echo.
click.progressbar(iterable=None, length=None, label=None, show_eta=True, show_percent=None, show_pos=False, item_show_func=None, fill_char='#', empty_char='-', bar_template='%(label)s [%(bar)s] %(info)s', info_sep=' ', width=36, file=None, color=None)

This function creates an iterable context manager that can be used to iterate over something while showing a progress bar. It will either iterate over the iterable or length items (that are counted up). While iteration happens, this function will print a rendered progress bar to the given file (defaults to stdout) and will attempt to calculate remaining time and more. By default, this progress bar will not be rendered if the file is not a terminal.

The context manager creates the progress bar. When the context manager is entered the progress bar is already displayed. With every iteration over the progress bar, the iterable passed to the bar is advanced and the bar is updated. When the context manager exits, a newline is printed and the progress bar is finalized on screen.

No printing must happen or the progress bar will be unintentionally destroyed.

Example usage:

with progressbar(items) as bar:
    for item in bar:
        do_something_with(item)

Alternatively, if no iterable is specified, one can manually update the progress bar through the update() method instead of directly iterating over the progress bar. The update method accepts the number of steps to increment the bar with:

with progressbar(length=chunks.total_bytes) as bar:
    for chunk in chunks:
        process_chunk(chunk)
        bar.update(chunks.bytes)

2.0 新版功能.

4.0 新版功能: Added the color parameter. Added a update method to the progressbar object.

参数:
  • iterable -- an iterable to iterate over. If not provided the length is required.
  • length -- the number of items to iterate over. By default the progressbar will attempt to ask the iterator about its length, which might or might not work. If an iterable is also provided this parameter can be used to override the length. If an iterable is not provided the progress bar will iterate over a range of that length.
  • label -- the label to show next to the progress bar.
  • show_eta -- enables or disables the estimated time display. This is automatically disabled if the length cannot be determined.
  • show_percent -- enables or disables the percentage display. The default is True if the iterable has a length or False if not.
  • show_pos -- enables or disables the absolute position display. The default is False.
  • item_show_func -- a function called with the current item which can return a string to show the current item next to the progress bar. Note that the current item can be None!
  • fill_char -- the character to use to show the filled part of the progress bar.
  • empty_char -- the character to use to show the non-filled part of the progress bar.
  • bar_template -- the format string to use as template for the bar. The parameters in it are label for the label, bar for the progress bar and info for the info section.
  • info_sep -- the separator between multiple info items (eta etc.)
  • width -- the width of the progress bar in characters, 0 means full terminal width
  • file -- the file to write to. If this is not a terminal then only the label is printed.
  • color -- controls if the terminal supports ANSI colors or not. The default is autodetection. This is only needed if ANSI codes are included anywhere in the progress bar output which is not the case by default.
click.clear()

Clears the terminal screen. This will have the effect of clearing the whole visible space of the terminal and moving the cursor to the top left. This does not do anything if not connected to a terminal.

2.0 新版功能.

click.style(text, fg=None, bg=None, bold=None, dim=None, underline=None, blink=None, reverse=None, reset=True)

Styles a text with ANSI styles and returns the new string. By default the styling is self contained which means that at the end of the string a reset code is issued. This can be prevented by passing reset=False.

Examples:

click.echo(click.style('Hello World!', fg='green'))
click.echo(click.style('ATTENTION!', blink=True))
click.echo(click.style('Some things', reverse=True, fg='cyan'))

Supported color names:

  • black (might be a gray)
  • red
  • green
  • yellow (might be an orange)
  • blue
  • magenta
  • cyan
  • white (might be light gray)
  • reset (reset the color code only)

2.0 新版功能.

参数:
  • text -- the string to style with ansi codes.
  • fg -- if provided this will become the foreground color.
  • bg -- if provided this will become the background color.
  • bold -- if provided this will enable or disable bold mode.
  • dim -- if provided this will enable or disable dim mode. This is badly supported.
  • underline -- if provided this will enable or disable underline.
  • blink -- if provided this will enable or disable blinking.
  • reverse -- if provided this will enable or disable inverse rendering (foreground becomes background and the other way round).
  • reset -- by default a reset-all code is added at the end of the string which means that styles do not carry over. This can be disabled to compose styles.
click.unstyle(text)

Removes ANSI styling information from a string. Usually it's not necessary to use this function as Click's echo function will automatically remove styling if necessary.

2.0 新版功能.

参数:text -- the text to remove style information from.
click.secho(text, file=None, nl=True, err=False, color=None, **styles)

This function combines echo() and style() into one call. As such the following two calls are the same:

click.secho('Hello World!', fg='green')
click.echo(click.style('Hello World!', fg='green'))

All keyword arguments are forwarded to the underlying functions depending on which one they go with.

2.0 新版功能.

click.edit(text=None, editor=None, env=None, require_save=True, extension='.txt', filename=None)

Edits the given text in the defined editor. If an editor is given (should be the full path to the executable but the regular operating system search path is used for finding the executable) it overrides the detected editor. Optionally, some environment variables can be used. If the editor is closed without changes, None is returned. In case a file is edited directly the return value is always None and require_save and extension are ignored.

If the editor cannot be opened a UsageError is raised.

Note for Windows: to simplify cross-platform usage, the newlines are automatically converted from POSIX to Windows and vice versa. As such, the message here will have \n as newline markers.

参数:
  • text -- the text to edit.
  • editor -- optionally the editor to use. Defaults to automatic detection.
  • env -- environment variables to forward to the editor.
  • require_save -- if this is true, then not saving in the editor will make the return value become None.
  • extension -- the extension to tell the editor about. This defaults to .txt but changing this might change syntax highlighting.
  • filename -- if provided it will edit this file instead of the provided text contents. It will not use a temporary file as an indirection in that case.
click.launch(url, wait=False, locate=False)

This function launches the given URL (or filename) in the default viewer application for this file type. If this is an executable, it might launch the executable in a new session. The return value is the exit code of the launched application. Usually, 0 indicates success.

Examples:

click.launch('http://click.pocoo.org/')
click.launch('/my/downloaded/file', locate=True)

2.0 新版功能.

参数:
  • url -- URL or filename of the thing to launch.
  • wait -- waits for the program to stop.
  • locate -- if this is set to True then instead of launching the application associated with the URL it will attempt to launch a file manager with the file located. This might have weird effects if the URL does not point to the filesystem.
click.getchar(echo=False)

Fetches a single character from the terminal and returns it. This will always return a unicode character and under certain rare circumstances this might return more than one character. The situations which more than one character is returned is when for whatever reason multiple characters end up in the terminal buffer or standard input was not actually a terminal.

Note that this will always read from the terminal, even if something is piped into the standard input.

2.0 新版功能.

参数:echo -- if set to True, the character read will also show up on the terminal. The default is to not show it.
click.pause(info='Press any key to continue ...', err=False)

This command stops execution and waits for the user to press any key to continue. This is similar to the Windows batch "pause" command. If the program is not run through a terminal, this command will instead do nothing.

2.0 新版功能.

4.0 新版功能: Added the err parameter.

参数:
  • info -- the info string to print before pausing.
  • err -- if set to message goes to stderr instead of stdout, the same as with echo.
click.get_terminal_size()

Returns the current size of the terminal as tuple in the form (width, height) in columns and rows.

click.get_binary_stream(name)

Returns a system stream for byte processing. This essentially returns the stream from the sys module with the given name but it solves some compatibility issues between different Python versions. Primarily this function is necessary for getting binary streams on Python 3.

参数:name -- the name of the stream to open. Valid names are 'stdin', 'stdout' and 'stderr'
click.get_text_stream(name, encoding=None, errors='strict')

Returns a system stream for text processing. This usually returns a wrapped stream around a binary stream returned from get_binary_stream() but it also can take shortcuts on Python 3 for already correctly configured streams.

参数:
  • name -- the name of the stream to open. Valid names are 'stdin', 'stdout' and 'stderr'
  • encoding -- overrides the detected default encoding.
  • errors -- overrides the default error mode.
click.open_file(filename, mode='r', encoding=None, errors='strict', lazy=False, atomic=False)

This is similar to how the File works but for manual usage. Files are opened non lazy by default. This can open regular files as well as stdin/stdout if '-' is passed.

If stdin/stdout is returned the stream is wrapped so that the context manager will not close the stream accidentally. This makes it possible to always use the function like this without having to worry to accidentally close a standard stream:

with open_file(filename) as f:
    ...

3.0 新版功能.

参数:
  • filename -- the name of the file to open (or '-' for stdin/stdout).
  • mode -- the mode in which to open the file.
  • encoding -- the encoding to use.
  • errors -- the error handling for this file.
  • lazy -- can be flipped to true to open the file lazily.
  • atomic -- in atomic mode writes go into a temporary file and it's moved on close.
click.get_app_dir(app_name, roaming=True, force_posix=False)

Returns the config folder for the application. The default behavior is to return whatever is most appropriate for the operating system.

To give you an idea, for an app called "Foo Bar", something like the following folders could be returned:

Mac OS X:
~/Library/Application Support/Foo Bar
Mac OS X (POSIX):
~/.foo-bar
Unix:
~/.config/foo-bar
Unix (POSIX):
~/.foo-bar
Win XP (roaming):
C:\Documents and Settings\<user>\Local Settings\Application Data\Foo Bar
Win XP (not roaming):
C:\Documents and Settings\<user>\Application Data\Foo Bar
Win 7 (roaming):
C:\Users\<user>\AppData\Roaming\Foo Bar
Win 7 (not roaming):
C:\Users\<user>\AppData\Local\Foo Bar

2.0 新版功能.

参数:
  • app_name -- the application name. This should be properly capitalized and can contain whitespace.
  • roaming -- controls if the folder should be roaming or not on Windows. Has no affect otherwise.
  • force_posix -- if this is set to True then on any POSIX system the folder will be stored in the home folder with a leading dot instead of the XDG config home or darwin's application support folder.
click.format_filename(filename, shorten=False)

Formats a filename for user display. The main purpose of this function is to ensure that the filename can be displayed at all. This will decode the filename to unicode if necessary in a way that it will not fail. Optionally, it can shorten the filename to not include the full path to the filename.

参数:
  • filename -- formats a filename for UI display. This will also convert the filename into unicode without failing.
  • shorten -- this optionally shortens the filename to strip of the path that leads up to it.

Commands

class click.BaseCommand(name, context_settings=None)

The base command implements the minimal API contract of commands. Most code will never use this as it does not implement a lot of useful functionality but it can act as the direct subclass of alternative parsing methods that do not depend on the Click parser.

For instance, this can be used to bridge Click and other systems like argparse or docopt.

Because base commands do not implement a lot of the API that other parts of Click take for granted, they are not supported for all operations. For instance, they cannot be used with the decorators usually and they have no built-in callback system.

在 2.0 版更改: Added the context_settings parameter.

参数:
  • name -- the name of the command to use unless a group overrides it.
  • context_settings -- an optional dictionary with defaults that are passed to the context object.
allow_extra_args = False

the default for the Context.allow_extra_args flag.

allow_interspersed_args = True

the default for the Context.allow_interspersed_args flag.

context_settings = None

an optional dictionary with defaults passed to the context.

ignore_unknown_options = False

the default for the Context.ignore_unknown_options flag.

invoke(ctx)

Given a context, this invokes the command. The default implementation is raising a not implemented error.

main(args=None, prog_name=None, complete_var=None, standalone_mode=True, **extra)

This is the way to invoke a script with all the bells and whistles as a command line application. This will always terminate the application after a call. If this is not wanted, SystemExit needs to be caught.

This method is also available by directly calling the instance of a Command.

3.0 新版功能: Added the standalone_mode flag to control the standalone mode.

参数:
  • args -- the arguments that should be used for parsing. If not provided, sys.argv[1:] is used.
  • prog_name -- the program name that should be used. By default the program name is constructed by taking the file name from sys.argv[0].
  • complete_var -- the environment variable that controls the bash completion support. The default is "_<prog_name>_COMPLETE" with prog name in uppercase.
  • standalone_mode -- the default behavior is to invoke the script in standalone mode. Click will then handle exceptions and convert them into error messages and the function will never return but shut down the interpreter. If this is set to False they will be propagated to the caller and the return value of this function is the return value of invoke().
  • extra -- extra keyword arguments are forwarded to the context constructor. See Context for more information.
make_context(info_name, args, parent=None, **extra)

This function when given an info name and arguments will kick off the parsing and create a new Context. It does not invoke the actual command callback though.

参数:
  • info_name -- the info name for this invokation. Generally this is the most descriptive name for the script or command. For the toplevel script it's usually the name of the script, for commands below it it's the name of the script.
  • args -- the arguments to parse as list of strings.
  • parent -- the parent context if available.
  • extra -- extra keyword arguments forwarded to the context constructor.
name = None

the name the command thinks it has. Upon registering a command on a Group the group will default the command name with this information. You should instead use the Context's info_name attribute.

parse_args(ctx, args)

Given a context and a list of arguments this creates the parser and parses the arguments, then modifies the context as necessary. This is automatically invoked by make_context().

class click.Command(name, context_settings=None, callback=None, params=None, help=None, epilog=None, short_help=None, options_metavar='[OPTIONS]', add_help_option=True)

Commands are the basic building block of command line interfaces in Click. A basic command handles command line parsing and might dispatch more parsing to commands nested below it.

在 2.0 版更改: Added the context_settings parameter.

参数:
  • name -- the name of the command to use unless a group overrides it.
  • context_settings -- an optional dictionary with defaults that are passed to the context object.
  • callback -- the callback to invoke. This is optional.
  • params -- the parameters to register with this command. This can be either Option or Argument objects.
  • help -- the help string to use for this command.
  • epilog -- like the help string but it's printed at the end of the help page after everything else.
  • short_help -- the short help to use for this command. This is shown on the command listing of the parent command.
  • add_help_option -- by default each command registers a --help option. This can be disabled by this parameter.
callback = None

the callback to execute when the command fires. This might be None in which case nothing happens.

collect_usage_pieces(ctx)

Returns all the pieces that go into the usage line and returns it as a list of strings.

format_epilog(ctx, formatter)

Writes the epilog into the formatter if it exists.

format_help(ctx, formatter)

Writes the help into the formatter if it exists.

This calls into the following methods:

format_help_text(ctx, formatter)

Writes the help text to the formatter if it exists.

format_options(ctx, formatter)

Writes all the options into the formatter if they exist.

format_usage(ctx, formatter)

Writes the usage line into the formatter.

get_help(ctx)

Formats the help into a string and returns it. This creates a formatter and will call into the following formatting methods:

get_help_option(ctx)

Returns the help option object.

get_help_option_names(ctx)

Returns the names for the help option.

invoke(ctx)

Given a context, this invokes the attached callback (if it exists) in the right way.

make_parser(ctx)

Creates the underlying option parser for this command.

params = None

the list of parameters for this command in the order they should show up in the help page and execute. Eager parameters will automatically be handled before non eager ones.

class click.MultiCommand(name=None, invoke_without_command=False, no_args_is_help=None, subcommand_metavar=None, chain=False, result_callback=None, **attrs)

A multi command is the basic implementation of a command that dispatches to subcommands. The most common version is the Group.

参数:
  • invoke_without_command -- this controls how the multi command itself is invoked. By default it's only invoked if a subcommand is provided.
  • no_args_is_help -- this controls what happens if no arguments are provided. This option is enabled by default if invoke_without_command is disabled or disabled if it's enabled. If enabled this will add --help as argument if no arguments are passed.
  • subcommand_metavar -- the string that is used in the documentation to indicate the subcommand place.
  • chain -- if this is set to True chaining of multiple subcommands is enabled. This restricts the form of commands in that they cannot have optional arguments but it allows multiple commands to be chained together.
  • result_callback -- the result callback to attach to this multi command.
format_commands(ctx, formatter)

Extra format methods for multi methods that adds all the commands after the options.

get_command(ctx, cmd_name)

Given a context and a command name, this returns a Command object if it exists or returns None.

list_commands(ctx)

Returns a list of subcommand names in the order they should appear.

result_callback = None

The result callback that is stored. This can be set or overridden with the resultcallback() decorator.

resultcallback(replace=False)

Adds a result callback to the chain command. By default if a result callback is already registered this will chain them but this can be disabled with the replace parameter. The result callback is invoked with the return value of the subcommand (or the list of return values from all subcommands if chaining is enabled) as well as the parameters as they would be passed to the main callback.

Example:

@click.group()
@click.option('-i', '--input', default=23)
def cli(input):
    return 42

@cli.resultcallback()
def process_result(result, input):
    return result + input

3.0 新版功能.

参数:replace -- if set to True an already existing result callback will be removed.
class click.Group(name=None, commands=None, **attrs)

A group allows a command to have subcommands attached. This is the most common way to implement nesting in Click.

参数:commands -- a dictionary of commands.
add_command(cmd, name=None)

Registers another Command with this group. If the name is not provided, the name of the command is used.

command(*args, **kwargs)

A shortcut decorator for declaring and attaching a command to the group. This takes the same arguments as command() but immediately registers the created command with this instance by calling into add_command().

commands = None

the registered subcommands by their exported names.

group(*args, **kwargs)

A shortcut decorator for declaring and attaching a group to the group. This takes the same arguments as group() but immediately registers the created command with this instance by calling into add_command().

class click.CommandCollection(name=None, sources=None, **attrs)

A command collection is a multi command that merges multiple multi commands together into one. This is a straightforward implementation that accepts a list of different multi commands as sources and provides all the commands for each of them.

add_source(multi_cmd)

Adds a new multi command to the chain dispatcher.

sources = None

The list of registered multi commands.

Parameters

class click.Parameter(param_decls=None, type=None, required=False, default=None, callback=None, nargs=None, metavar=None, expose_value=True, is_eager=False, envvar=None)

A parameter to a command comes in two versions: they are either Options or Arguments. Other subclasses are currently not supported by design as some of the internals for parsing are intentionally not finalized.

Some settings are supported by both options and arguments.

在 2.0 版更改: Changed signature for parameter callback to also be passed the parameter. In Click 2.0, the old callback format will still work, but it will raise a warning to give you change to migrate the code easier.

参数:
  • param_decls -- the parameter declarations for this option or argument. This is a list of flags or argument names.
  • type -- the type that should be used. Either a ParamType or a Python type. The later is converted into the former automatically if supported.
  • required -- controls if this is optional or not.
  • default -- the default value if omitted. This can also be a callable, in which case it's invoked when the default is needed without any arguments.
  • callback -- a callback that should be executed after the parameter was matched. This is called as fn(ctx, param, value) and needs to return the value. Before Click 2.0, the signature was (ctx, value).
  • nargs -- the number of arguments to match. If not 1 the return value is a tuple instead of single value. The default for nargs is 1 (except if the type is a tuple, then it's the arity of the tuple).
  • metavar -- how the value is represented in the help page.
  • expose_value -- if this is True then the value is passed onwards to the command callback and stored on the context, otherwise it's skipped.
  • is_eager -- eager values are processed before non eager ones. This should not be set for arguments or it will inverse the order of processing.
  • envvar -- a string or list of strings that are environment variables that should be checked.
get_default(ctx)

Given a context variable this calculates the default value.

human_readable_name

Returns the human readable name of this parameter. This is the same as the name for options, but the metavar for arguments.

process_value(ctx, value)

Given a value and context this runs the logic to convert the value as necessary.

type_cast_value(ctx, value)

Given a value this runs it properly through the type system. This automatically handles things like nargs and multiple as well as composite types.

class click.Option(param_decls=None, show_default=False, prompt=False, confirmation_prompt=False, hide_input=False, is_flag=None, flag_value=None, multiple=False, count=False, allow_from_autoenv=True, type=None, help=None, **attrs)

Options are usually optional values on the command line and have some extra features that arguments don't have.

All other parameters are passed onwards to the parameter constructor.

参数:
  • show_default -- controls if the default value should be shown on the help page. Normally, defaults are not shown.
  • prompt -- if set to True or a non empty string then the user will be prompted for input if not set. If set to True the prompt will be the option name capitalized.
  • confirmation_prompt -- if set then the value will need to be confirmed if it was prompted for.
  • hide_input -- if this is True then the input on the prompt will be hidden from the user. This is useful for password input.
  • is_flag -- forces this option to act as a flag. The default is auto detection.
  • flag_value -- which value should be used for this flag if it's enabled. This is set to a boolean automatically if the option string contains a slash to mark two options.
  • multiple -- if this is set to True then the argument is accepted multiple times and recorded. This is similar to nargs in how it works but supports arbitrary number of arguments.
  • count -- this flag makes an option increment an integer.
  • allow_from_autoenv -- if this is enabled then the value of this parameter will be pulled from an environment variable in case a prefix is defined on the context.
  • help -- the help string.
class click.Argument(param_decls, required=None, **attrs)

Arguments are positional parameters to a command. They generally provide fewer features than options but can have infinite nargs and are required by default.

All parameters are passed onwards to the parameter constructor.

Context

class click.Context(command, parent=None, info_name=None, obj=None, auto_envvar_prefix=None, default_map=None, terminal_width=None, max_content_width=None, resilient_parsing=False, allow_extra_args=None, allow_interspersed_args=None, ignore_unknown_options=None, help_option_names=None, token_normalize_func=None, color=None)

The context is a special internal object that holds state relevant for the script execution at every single level. It's normally invisible to commands unless they opt-in to getting access to it.

The context is useful as it can pass internal objects around and can control special execution features such as reading data from environment variables.

A context can be used as context manager in which case it will call close() on teardown.

2.0 新版功能: Added the resilient_parsing, help_option_names, token_normalize_func parameters.

3.0 新版功能: Added the allow_extra_args and allow_interspersed_args parameters.

4.0 新版功能: Added the color, ignore_unknown_options, and max_content_width parameters.

参数:
  • command -- the command class for this context.
  • parent -- the parent context.
  • info_name -- the info name for this invocation. Generally this is the most descriptive name for the script or command. For the toplevel script it is usually the name of the script, for commands below it it's the name of the script.
  • obj -- an arbitrary object of user data.
  • auto_envvar_prefix -- the prefix to use for automatic environment variables. If this is None then reading from environment variables is disabled. This does not affect manually set environment variables which are always read.
  • default_map -- a dictionary (like object) with default values for parameters.
  • terminal_width -- the width of the terminal. The default is inherit from parent context. If no context defines the terminal width then auto detection will be applied.
  • max_content_width -- the maximum width for content rendered by Click (this currently only affects help pages). This defaults to 80 characters if not overridden. In other words: even if the terminal is larger than that, Click will not format things wider than 80 characters by default. In addition to that, formatters might add some safety mapping on the right.
  • resilient_parsing -- if this flag is enabled then Click will parse without any interactivity or callback invocation. This is useful for implementing things such as completion support.
  • allow_extra_args -- if this is set to True then extra arguments at the end will not raise an error and will be kept on the context. The default is to inherit from the command.
  • allow_interspersed_args -- if this is set to False then options and arguments cannot be mixed. The default is to inherit from the command.
  • ignore_unknown_options -- instructs click to ignore options it does not know and keeps them for later processing.
  • help_option_names -- optionally a list of strings that define how the default help parameter is named. The default is ['--help'].
  • token_normalize_func -- an optional function that is used to normalize tokens (options, choices, etc.). This for instance can be used to implement case insensitive behavior.
  • color -- controls if the terminal supports ANSI colors or not. The default is autodetection. This is only needed if ANSI codes are used in texts that Click prints which is by default not the case. This for instance would affect help output.
abort()

Aborts the script.

allow_extra_args = None

Indicates if the context allows extra args or if it should fail on parsing.

3.0 新版功能.

allow_interspersed_args = None

Indicates if the context allows mixing of arguments and options or not.

3.0 新版功能.

args = None

the leftover arguments.

call_on_close(f)

This decorator remembers a function as callback that should be executed when the context tears down. This is most useful to bind resource handling to the script execution. For instance, file objects opened by the File type will register their close callbacks here.

参数:f -- the function to execute on teardown.
close()

Invokes all close callbacks.

color = None

Controls if styling output is wanted or not.

command = None

the Command for this context.

command_path

The computed command path. This is used for the usage information on the help page. It's automatically created by combining the info names of the chain of contexts to the root.

ensure_object(object_type)

Like find_object() but sets the innermost object to a new instance of object_type if it does not exist.

exit(code=0)

Exits the application with a given exit code.

fail(message)

Aborts the execution of the program with a specific error message.

参数:message -- the error message to fail with.
find_object(object_type)

Finds the closest object of a given type.

find_root()

Finds the outermost context.

forward(*args, **kwargs)

Similar to invoke() but fills in default keyword arguments from the current context if the other command expects it. This cannot invoke callbacks directly, only other commands.

get_help()

Helper method to get formatted help page for the current context and command.

get_usage()

Helper method to get formatted usage string for the current context and command.

help_option_names = None

The names for the help options.

ignore_unknown_options = None

Instructs click to ignore options that a command does not understand and will store it on the context for later processing. This is primarily useful for situations where you want to call into external programs. Generally this pattern is strongly discouraged because it's not possibly to losslessly forward all arguments.

4.0 新版功能.

info_name = None

the descriptive information name

invoke(*args, **kwargs)

Invokes a command callback in exactly the way it expects. There are two ways to invoke this method:

  1. the first argument can be a callback and all other arguments and keyword arguments are forwarded directly to the function.
  2. the first argument is a click command object. In that case all arguments are forwarded as well but proper click parameters (options and click arguments) must be keyword arguments and Click will fill in defaults.

Note that before Click 3.2 keyword arguments were not properly filled in against the intention of this code and no context was created. For more information about this change and why it was done in a bugfix release see Upgrading to 3.2.

invoked_subcommand = None

This flag indicates if a subcommand is going to be executed. A group callback can use this information to figure out if it's being executed directly or because the execution flow passes onwards to a subcommand. By default it's None, but it can be the name of the subcommand to execute.

If chaining is enabled this will be set to '*' in case any commands are executed. It is however not possible to figure out which ones. If you require this knowledge you should use a resultcallback().

lookup_default(name)

Looks up the default for a parameter name. This by default looks into the default_map if available.

make_formatter()

Creates the formatter for the help and usage output.

max_content_width = None

The maximum width of formatted content (None implies a sensible default which is 80 for most things).

meta

This is a dictionary which is shared with all the contexts that are nested. It exists so that click utiltiies can store some state here if they need to. It is however the responsibility of that code to manage this dictionary well.

The keys are supposed to be unique dotted strings. For instance module paths are a good choice for it. What is stored in there is irrelevant for the operation of click. However what is important is that code that places data here adheres to the general semantics of the system.

Example usage:

LANG_KEY = __name__ + '.lang'

def set_language(value):
    ctx = get_current_context()
    ctx.meta[LANG_KEY] = value

def get_language():
    return get_current_context().meta.get(LANG_KEY, 'en_US')

5.0 新版功能.

obj = None

the user object stored.

params = None

the parsed parameters except if the value is hidden in which case it's not remembered.

parent = None

the parent context or None if none exists.

protected_args = None

protected arguments. These are arguments that are prepended to args when certain parsing scenarios are encountered but must be never propagated to another arguments. This is used to implement nested parsing.

resilient_parsing = None

Indicates if resilient parsing is enabled. In that case Click will do its best to not cause any failures.

scope(*args, **kwds)

This helper method can be used with the context object to promote it to the current thread local (see get_current_context()). The default behavior of this is to invoke the cleanup functions which can be disabled by setting cleanup to False. The cleanup functions are typically used for things such as closing file handles.

If the cleanup is intended the context object can also be directly used as a context manager.

Example usage:

with ctx.scope():
    assert get_current_context() is ctx

This is equivalent:

with ctx:
    assert get_current_context() is ctx

5.0 新版功能.

参数:cleanup -- controls if the cleanup functions should be run or not. The default is to run these functions. In some situations the context only wants to be temporarily pushed in which case this can be disabled. Nested pushes automatically defer the cleanup.
terminal_width = None

The width of the terminal (None is autodetection).

token_normalize_func = None

An optional normalization function for tokens. This is options, choices, commands etc.

click.get_current_context(silent=False)

Returns the current click context. This can be used as a way to access the current context object from anywhere. This is a more implicit alternative to the pass_context() decorator. This function is primarily useful for helpers such as echo() which might be interested in changing it's behavior based on the current context.

To push the current context, Context.scope() can be used.

5.0 新版功能.

参数:silent -- is set to True the return value is None if no context is available. The default behavior is to raise a RuntimeError.

Types

click.STRING = STRING

A unicode string parameter type which is the implicit default. This can also be selected by using str as type.

click.INT = INT

An integer parameter. This can also be selected by using int as type.

click.FLOAT = FLOAT

A floating point value parameter. This can also be selected by using float as type.

click.BOOL = BOOL

A boolean parameter. This is the default for boolean flags. This can also be selected by using bool as a type.

click.UUID = UUID

A UUID parameter.

click.UNPROCESSED = UNPROCESSED

A dummy parameter type that just does nothing. From a user's perspective this appears to just be the same as STRING but internally no string conversion takes place. This is necessary to achieve the same bytes/unicode behavior on Python 2/3 in situations where you want to not convert argument types. This is usually useful when working with file paths as they can appear in bytes and unicode.

For path related uses the Path type is a better choice but there are situations where an unprocessed type is useful which is why it is is provided.

4.0 新版功能.

class click.File(mode='r', encoding=None, errors='strict', lazy=None, atomic=False)

Declares a parameter to be a file for reading or writing. The file is automatically closed once the context tears down (after the command finished working).

Files can be opened for reading or writing. The special value - indicates stdin or stdout depending on the mode.

By default, the file is opened for reading text data, but it can also be opened in binary mode or for writing. The encoding parameter can be used to force a specific encoding.

The lazy flag controls if the file should be opened immediately or upon first IO. The default is to be non lazy for standard input and output streams as well as files opened for reading, lazy otherwise.

Starting with Click 2.0, files can also be opened atomically in which case all writes go into a separate file in the same folder and upon completion the file will be moved over to the original location. This is useful if a file regularly read by other users is modified.

See 文件参数 for more information.

class click.Path(exists=False, file_okay=True, dir_okay=True, writable=False, readable=True, resolve_path=False, allow_dash=False, path_type=None)

The path type is similar to the File type but it performs different checks. First of all, instead of returning an open file handle it returns just the filename. Secondly, it can perform various basic checks about what the file or directory should be.

在 6.0 版更改: allow_dash was added.

参数:
  • exists -- if set to true, the file or directory needs to exist for this value to be valid. If this is not required and a file does indeed not exist, then all further checks are silently skipped.
  • file_okay -- controls if a file is a possible value.
  • dir_okay -- controls if a directory is a possible value.
  • writable -- if true, a writable check is performed.
  • readable -- if true, a readable check is performed.
  • resolve_path -- if this is true, then the path is fully resolved before the value is passed onwards. This means that it's absolute and symlinks are resolved.
  • allow_dash -- If this is set to True, a single dash to indicate standard streams is permitted.
  • type -- optionally a string type that should be used to represent the path. The default is None which means the return value will be either bytes or unicode depending on what makes most sense given the input data Click deals with.
class click.Choice(choices)

The choice type allows a value to be checked against a fixed set of supported values. All of these values have to be strings.

See 选择选项 for an example.

class click.IntRange(min=None, max=None, clamp=False)

A parameter that works similar to click.INT but restricts the value to fit into a range. The default behavior is to fail if the value falls outside the range, but it can also be silently clamped between the two edges.

See 范围选项 for an example.

class click.Tuple(types)

The default behavior of Click is to apply a type on a value directly. This works well in most cases, except for when nargs is set to a fixed count and different types should be used for different items. In this case the Tuple type can be used. This type can only be used if nargs is set to a fixed number.

For more information see 使用元组(tuple)代替多个值的选项.

This can be selected by using a Python tuple literal as a type.

参数:types -- a list of types that should be used for the tuple items.
class click.ParamType

Helper for converting values through types. The following is necessary for a valid type:

  • it needs a name
  • it needs to pass through None unchanged
  • it needs to convert from a string
  • it needs to convert its result type through unchanged (eg: needs to be idempotent)
  • it needs to be able to deal with param and context being None. This can be the case when the object is used with prompt inputs.
convert(value, param, ctx)

Converts the value. This is not invoked for values that are None (the missing value).

envvar_list_splitter = None

if a list of this type is expected and the value is pulled from a string environment variable, this is what splits it up. None means any whitespace. For all parameters the general rule is that whitespace splits them up. The exception are paths and files which are split by os.path.pathsep by default (":" on Unix and ";" on Windows).

fail(message, param=None, ctx=None)

Helper method to fail with an invalid value message.

get_metavar(param)

Returns the metavar default for this param if it provides one.

get_missing_message(param)

Optionally might return extra information about a missing parameter.

2.0 新版功能.

name = None

the descriptive name of this type

split_envvar_value(rv)

Given a value from an environment variable this splits it up into small chunks depending on the defined envvar list splitter.

If the splitter is set to None, which means that whitespace splits, then leading and trailing whitespace is ignored. Otherwise, leading and trailing splitters usually lead to empty items being included.

Exceptions

exception click.ClickException(message)

An exception that Click can handle and show to the user.

exception click.Abort

An internal signalling exception that signals Click to abort.

exception click.UsageError(message, ctx=None)

An internal exception that signals a usage error. This typically aborts any further handling.

参数:
  • message -- the error message to display.
  • ctx -- optionally the context that caused this error. Click will fill in the context automatically in some situations.
exception click.BadParameter(message, ctx=None, param=None, param_hint=None)

An exception that formats out a standardized error message for a bad parameter. This is useful when thrown from a callback or type as Click will attach contextual information to it (for instance, which parameter it is).

2.0 新版功能.

参数:
  • param -- the parameter object that caused this error. This can be left out, and Click will attach this info itself if possible.
  • param_hint -- a string that shows up as parameter name. This can be used as alternative to param in cases where custom validation should happen. If it is a string it's used as such, if it's a list then each item is quoted and separated.
exception click.FileError(filename, hint=None)

Raised if a file cannot be opened.

exception click.NoSuchOption(option_name, message=None, possibilities=None, ctx=None)

Raised if click attempted to handle an option that does not exist.

4.0 新版功能.

exception click.BadOptionUsage(message, ctx=None)

Raised if an option is generally supplied but the use of the option was incorrect. This is for instance raised if the number of arguments for an option is not correct.

4.0 新版功能.

exception click.BadArgumentUsage(message, ctx=None)

Raised if an argument is generally supplied but the use of the argument was incorrect. This is for instance raised if the number of values for an argument is not correct.

6.0 新版功能.

Formatting

class click.HelpFormatter(indent_increment=2, width=None, max_width=None)

This class helps with formatting text-based help pages. It's usually just needed for very special internal cases, but it's also exposed so that developers can write their own fancy outputs.

At present, it always writes into memory.

参数:
  • indent_increment -- the additional increment for each level.
  • width -- the width for the text. This defaults to the terminal width clamped to a maximum of 78.
dedent()

Decreases the indentation.

getvalue()

Returns the buffer contents.

indent()

Increases the indentation.

indentation(*args, **kwds)

A context manager that increases the indentation.

section(*args, **kwds)

Helpful context manager that writes a paragraph, a heading, and the indents.

参数:name -- the section name that is written as heading.
write(string)

Writes a unicode string into the internal buffer.

write_dl(rows, col_max=30, col_spacing=2)

Writes a definition list into the buffer. This is how options and commands are usually formatted.

参数:
  • rows -- a list of two item tuples for the terms and values.
  • col_max -- the maximum width of the first column.
  • col_spacing -- the number of spaces between the first and second column.
write_heading(heading)

Writes a heading into the buffer.

write_paragraph()

Writes a paragraph into the buffer.

write_text(text)

Writes re-indented text into the buffer. This rewraps and preserves paragraphs.

write_usage(prog, args='', prefix='Usage: ')

Writes a usage line into the buffer.

参数:
  • prog -- the program name.
  • args -- whitespace separated list of arguments.
  • prefix -- the prefix for the first line.
click.wrap_text(text, width=78, initial_indent='', subsequent_indent='', preserve_paragraphs=False)

A helper function that intelligently wraps text. By default, it assumes that it operates on a single paragraph of text but if the preserve_paragraphs parameter is provided it will intelligently handle paragraphs (defined by two empty lines).

If paragraphs are handled, a paragraph can be prefixed with an empty line containing the \b character (\x08) to indicate that no rewrapping should happen in that block.

参数:
  • text -- the text that should be rewrapped.
  • width -- the maximum width for the text.
  • initial_indent -- the initial indent that should be placed on the first line as a string.
  • subsequent_indent -- the indent string that should be placed on each consecutive line.
  • preserve_paragraphs -- if this flag is set then the wrapping will intelligently handle paragraphs.

Parsing

class click.OptionParser(ctx=None)

The option parser is an internal class that is ultimately used to parse options and arguments. It's modelled after optparse and brings a similar but vastly simplified API. It should generally not be used directly as the high level Click classes wrap it for you.

It's not nearly as extensible as optparse or argparse as it does not implement features that are implemented on a higher level (such as types or defaults).

参数:ctx -- optionally the Context where this parser should go with.
add_argument(dest, nargs=1, obj=None)

Adds a positional argument named dest to the parser.

The obj can be used to identify the option in the order list that is returned from the parser.

add_option(opts, dest, action=None, nargs=1, const=None, obj=None)

Adds a new option named dest to the parser. The destination is not inferred (unlike with optparse) and needs to be explicitly provided. Action can be any of store, store_const, append, appnd_const or count.

The obj can be used to identify the option in the order list that is returned from the parser.

allow_interspersed_args = None

This controls how the parser deals with interspersed arguments. If this is set to False, the parser will stop on the first non-option. Click uses this to implement nested subcommands safely.

ctx = None

The Context for this parser. This might be None for some advanced use cases.

ignore_unknown_options = None

This tells the parser how to deal with unknown options. By default it will error out (which is sensible), but there is a second mode where it will ignore it and continue processing after shifting all the unknown options into the resulting args.

parse_args(args)

Parses positional arguments and returns (values, args, order) for the parsed options and arguments as well as the leftover arguments if there are any. The order is a list of objects as they appear on the command line. If arguments appear multiple times they will be memorized multiple times as well.

Testing

class click.testing.CliRunner(charset=None, env=None, echo_stdin=False)

The CLI runner provides functionality to invoke a Click command line script for unittesting purposes in a isolated environment. This only works in single-threaded systems without any concurrency as it changes the global interpreter state.

参数:
  • charset -- the character set for the input and output data. This is UTF-8 by default and should not be changed currently as the reporting to Click only works in Python 2 properly.
  • env -- a dictionary with environment variables for overriding.
  • echo_stdin -- if this is set to True, then reading from stdin writes to stdout. This is useful for showing examples in some circumstances. Note that regular prompts will automatically echo the input.
get_default_prog_name(cli)

Given a command object it will return the default program name for it. The default is the name attribute or "root" if not set.

invoke(cli, args=None, input=None, env=None, catch_exceptions=True, color=False, **extra)

Invokes a command in an isolated environment. The arguments are forwarded directly to the command line script, the extra keyword arguments are passed to the main() function of the command.

This returns a Result object.

3.0 新版功能: The catch_exceptions parameter was added.

在 3.0 版更改: The result object now has an exc_info attribute with the traceback if available.

4.0 新版功能: The color parameter was added.

参数:
  • cli -- the command to invoke
  • args -- the arguments to invoke
  • input -- the input data for sys.stdin.
  • env -- the environment overrides.
  • catch_exceptions -- Whether to catch any other exceptions than SystemExit.
  • extra -- the keyword arguments to pass to main().
  • color -- whether the output should contain color codes. The application can still override this explicitly.
isolated_filesystem(*args, **kwds)

A context manager that creates a temporary folder and changes the current working directory to it for isolated filesystem tests.

isolation(*args, **kwds)

A context manager that sets up the isolation for invoking of a command line tool. This sets up stdin with the given input data and os.environ with the overrides from the given dictionary. This also rebinds some internals in Click to be mocked (like the prompt functionality).

This is automatically done in the invoke() method.

4.0 新版功能: The color parameter was added.

参数:
  • input -- the input stream to put into sys.stdin.
  • env -- the environment overrides as dictionary.
  • color -- whether the output should contain color codes. The application can still override this explicitly.
make_env(overrides=None)

Returns the environment overrides for invoking a script.

class click.testing.Result(runner, output_bytes, exit_code, exception, exc_info=None)

Holds the captured result of an invoked CLI script.

exc_info = None

The traceback

exception = None

The exception that happend if one did.

exit_code = None

The exit code as integer.

output

The output as unicode string.

output_bytes = None

The output as bytes.

runner = None

The runner that created the result

Miscellaneous Pages

click-contrib

As the userbase of Click grows, more and more major feature requests pop up in Click's bugtracker. As reasonable as it may be for those features to be bundled with Click instead of being a standalone project, many of those requested features are either highly experimental or have unproven practical use, while potentially being a burden to maintain.

This is why click-contrib exists. The GitHub organization is a collection of possibly experimental third-party packages whose featureset does not belong into Click, but also a playground for major features that may be added to Click in the future. It is also meant to coordinate and concentrate effort on writing third-party extensions for Click, and to ease the effort of searching for such extensions. In that sense it could be described as a low-maintenance alternative to extension repositories of other frameworks.

Please note that the quality and stability of those packages may be different than what you expect from Click itself. While published under a common organization, they are still projects separate from Click.

Upgrading To Newer Releases

Click attempts the highest level of backwards compatibility but sometimes this is not entirely possible. In case we need to break backwards compatibility this document gives you information about how to upgrade or handle backwards compatibility properly.

Upgrading to 3.2

Click 3.2 had to perform two changes to multi commands which were triggered by a change between Click 2 and Click 3 that had bigger consequences than anticipated.

Context Invokes

Click 3.2 contains a fix for the Context.invoke() function when used with other commands. The original intention of this function was to invoke the other command as as if it came from the command line when it was passed a context object instead of a function. This use was only documented in a single place in the documentation before and there was no proper explanation for the method in the API documentation.

The core issue is that before 3.2 this call worked against intentions:

ctx.invoke(other_command, 'arg1', 'arg2')

This was never intended to work as it does not allow Click to operate on the parameters. Given that this pattern was never documented and ill intended the decision was made to change this behavior in a bugfix release before it spreads by accident and developers depend on it.

The correct invocation for the above command is the following:

ctx.invoke(other_command, name_of_arg1='arg1', name_of_arg2='arg2')

This also allowed us to fix the issue that defaults were not handled properly by this function.

Multicommand Chaining API

Click 3 introduced multicommand chaning. This required a change in how Click internally dispatches. Unfortunately this change was not correctly implemented and it appeared that it was possible to provide an API that can inform the super command about all the subcommands that will be invoked.

This assumption however does not work with one of the API guarantees that have been given in the past. As such this functionality has been removed in 3.2 as it was already broken. Instead the accidentally broken functionality of the Context.invoked_subcommand attribute was restored.

If you do require the know which exact commands will be invoked there are different ways to cope with this. The first one is to let the subcommands all return functions and then to invoke the functions in a Context.resultcallback().

Upgrading to 2.0

Click 2.0 has one breaking change which is the signature for parameter callbacks. Before 2.0, the callback was invoked with (ctx, value) whereas now it's (ctx, param, value). This change was necessary as it otherwise made reusing callbacks too complicated.

To ease the transition Click will still accept old callbacks. Starting with Click 3.0 it will start to issue a warning to stderr to encourage you to upgrade.

In case you want to support both Click 1.0 and Click 2.0, you can make a simple decorator that adjusts the signatures:

import click
from functools import update_wrapper

def compatcallback(f):
    # Click 1.0 does not have a version string stored, so we need to
    # use getattr here to be safe.
    if getattr(click, '__version__', '0.0') >= '2.0':
        return f
    return update_wrapper(lambda ctx, value: f(ctx, None, value), f)

With that helper you can then write something like this:

@compatcallback
def callback(ctx, param, value):
    return value.upper()

Note that because Click 1.0 did not pass a parameter, the param argument here would be None, so a compatibility callback could not use that argument.

License

Click is licensed under a three-clause BSD License. It basically means: do whatever you want with it as long as the copyright in Click sticks around, the conditions are not modified and the disclaimer is present. Furthermore, you must not use the names of the authors to promote derivatives of the software without written consent.

License Text

Copyright (c) 2014 by Armin Ronacher.

Click uses parts of optparse written by Gregory P. Ward and maintained by the Python software foundation. This is limited to code in the parser.py module:

Copyright (c) 2001-2006 Gregory P. Ward. All rights reserved. Copyright (c) 2002-2006 Python Software Foundation. All rights reserved.

Some rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.