选项

向命令添加选项可以通过 option() 装饰者。因为选项可以有不同的版本,所以有大量的参数来配置它们的行为。click中的选项与 positional arguments .

为你的选择命名

选项的名称在调用修饰函数时将用作Python参数名。这可以从选项名称中推断出来,也可以显式给出。名称作为装饰器的位置参数。

按以下顺序选择名称

  1. 如果名称没有加前缀,则它将用作Python参数名,而不会在命令行中将其视为选项名。

  2. 如果至少有一个名称以两个破折号为前缀,则使用给定的第一个名称作为名称。

  3. 以一个破折号为前缀的名字在其他情况下使用。

要获取Python参数名,所选名称将转换为小写,最多删除两个破折号作为前缀,其他短划线转换为下划线。

@click.command()
@click.option('-s', '--string-to-echo')
def echo(string_to_echo):
    click.echo(string_to_echo)
@click.command()
@click.option('-s', '--string-to-echo', 'string')
def echo(string):
    click.echo(string)
  • "-f", "--foo-bar", the name is foo_bar

  • "-x", the name is x

  • "-f", "--filename", "dest", the name is dest

  • "--CamelCase", the name is camelcase

  • "-f", "-fb", the name is f

  • "--f", "--foo-bar", the name is f

  • "---f", the name is _f

基本值选项

最基本的选项是值选项。这些选项接受一个值参数。如果未提供类型,则使用默认值的类型。如果没有提供默认值,则假定类型为 STRING . 除非显式指定了名称,否则参数的名称是定义的第一个长选项;否则将使用第一个短选项。默认情况下,不需要选项,但是要使选项成为必需的,只需传入 required=True 作为修饰符的参数。

@click.command()
@click.option('--n', default=1)
def dots(n):
    click.echo('.' * n)
# How to make an option required
@click.command()
@click.option('--n', required=True, type=int)
def dots(n):
    click.echo('.' * n)
# How to use a Python reserved word such as `from` as a parameter
@click.command()
@click.option('--from', '-f', 'from_')
@click.option('--to', '-t')
def reserved_param_name(from_, to):
    click.echo(f"from {from_} to {to}")

在命令行上:

$ dots --n=2
..

在这种情况下,选项的类型为 INT 因为默认值是一个整数。

要在显示命令帮助时显示默认值,请使用 show_default=True

@click.command()
@click.option('--n', default=1, show_default=True)
def dots(n):
    click.echo('.' * n)
$ dots --help
Usage: dots [OPTIONS]

Options:
  --n INTEGER  [default: 1]
  --help       Show this message and exit.

对于单选项布尔标志,如果缺省值为FALSE,则默认为隐藏。

@click.command()
@click.option('--n', default=1, show_default=True)
@click.option("--gr", is_flag=True, show_default=True, default=False, help="Greet the world.")
@click.option("--br", is_flag=True, show_default=True, default=True, help="Add a thematic break")
def dots(n, gr, br):
    if gr:
        click.echo('Hello world!')
    click.echo('.' * n)
    if br:
        click.echo('-' * n)
$ dots --help
Usage: dots [OPTIONS]

Options:
  --n INTEGER  [default: 1]
  --gr         Greet the world.
  --br         Add a thematic break  [default: True]
  --help       Show this message and exit.

多值选项

有时,你可以选择多个论点。对于选项,只支持固定数量的参数。这可以通过 nargs 参数。这些值随后存储为一个元组。

@click.command()
@click.option('--pos', nargs=2, type=float)
def findme(pos):
    a, b = pos
    click.echo(f"{a} / {b}")

在命令行上:

$ findme --pos 2.0 3.0
2.0 / 3.0

元组作为多值选项

Changelog

在 4.0 版本加入.

你可以通过使用 nargs 设置为特定的数字,结果元组中的每个项都属于同一类型。这可能不是你想要的。通常,您可能希望对元组中的不同索引使用不同的类型。为此,可以直接将元组指定为类型:

@click.command()
@click.option('--item', type=(str, int))
def putitem(item):
    name, id = item
    click.echo(f"name={name} id={id}")

在命令行上:

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

通过使用tuple文本作为类型, nargs 自动设置为元组的长度和 click.Tuple 类型将自动使用。因此,上述示例等效于:

@click.command()
@click.option('--item', nargs=2, type=click.Tuple([str, int]))
def putitem(item):
    name, id = item
    click.echo(f"name={name} id={id}")

多种选择方案

类似于 nargs ,还有一种情况是,希望支持一个参数被多次提供并记录所有值,而不仅仅是最后一个。例如, git commit -m foo -m bar 将为提交消息记录两行: 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

当通过 default 具有 multiple=True ,默认值必须是列表或元组,否则将被解释为单个字符的列表。

@click.option("--format", multiple=True, default=["json"])

计数

在一些非常罕见的情况下,使用选项的重复来向上计数整数是很有趣的。这可用于详细标志,例如:

@click.command()
@click.option('-v', '--verbose', count=True)
def log(verbose):
    click.echo(f"Verbosity: {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
LINUX!!!!111
$ info --no-shout
linux
$ info
linux

如果您真的不想关闭开关,您只需定义一个开关并手动通知Click某个东西是一个标志:

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
LINUX!!!!111
$ info
linux

请注意,如果选项中已经包含斜线(例如,如果使用Windows样式参数 / 是前缀字符),您也可以通过 ; 而是:

@click.command()
@click.option('/debug;/no-debug')
def log(debug):
    click.echo(f"debug={debug}")

if __name__ == '__main__':
    log()
Changelog

在 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
LINUX
$ info --lower
linux
$ info
LINUX

选择选项

有时,您希望让一个参数成为一个值列表的选项。在这种情况下,你可以使用 Choice 类型。它可以用有效值列表实例化。将返回最初传递的选项,而不是在命令行上传递的str。令牌规范化函数和 case_sensitive=False 可能导致两者不同,但仍然匹配。

例子:

@click.command()
@click.option('--hash-type',
              type=click.Choice(['MD5', 'SHA1'], case_sensitive=False))
def digest(hash_type):
    click.echo(hash_type)

它是什么样子的:

$ digest --hash-type=MD5
MD5

$ digest --hash-type=md5
MD5

$ digest --hash-type=foo
Usage: digest [OPTIONS]
Try 'digest --help' for help.

Error: Invalid value for '--hash-type': 'foo' is not one of 'MD5', 'SHA1'.

$ digest --help
Usage: digest [OPTIONS]

Options:
  --hash-type [MD5|SHA1]
  --help                  Show this message and exit.

只将选项作为列表或元组传递。其他ITerable(如生成器)可能会导致意外结果。

选项与具有 multiple=True . 如果A default 值用 multiple=True ,它应该是有效选择的列表或元组。

在考虑到 case_sensitive 以及任何指定的令牌规范化函数。

Changelog

在 7.1 版本发生变更: 选项的结果值将始终是最初传递的选项之一,而不管 case_sensitive .

提示

在某些情况下,您需要可以从命令行提供的参数,但如果没有提供,则请求用户输入。这可以通过定义提示字符串通过Click来实现。

例子:

@click.command()
@click.option('--name', prompt=True)
def hello(name):
    click.echo(f"Hello {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(f"Hello {name}!")

它是什么样子的:

$ hello
Your name please: John
Hello John!

建议不要将prompt与设置为True的multiple标志一起使用。相反,在函数中以交互方式提示。

默认情况下,如果没有通过命令行传递输入,则会提示用户输入。要关闭此行为,请参见 可选值 .

密码提示

Click还支持隐藏提示和请求确认。这对于输入密码很有用:

import codecs

@click.command()
@click.option(
    "--password", prompt=True, hide_input=True,
    confirmation_prompt=True
)
def encode(password):
    click.echo(f"encoded: {codecs.encode(password, 'rot13')}")
$ encode
Password: 
Repeat for confirmation: 
encoded: frperg

因为这种参数组合非常常见,所以也可以用 password_option() 装饰者:

@click.command()
@click.password_option()
def encrypt(password):
    click.echo(f"encoded: to {codecs.encode(password, 'rot13')}")

提示的动态默认值

这个 auto_envvar_prefixdefault_map 上下文选项允许程序从环境或配置文件中读取选项值。但是,这会覆盖提示机制,这样用户就不能选择以交互方式更改值。

如果要让用户配置默认值,但在命令行上未指定该选项时仍会提示用户,则可以通过提供一个Callable作为默认值来进行配置。例如,要从环境中获取默认值,请执行以下操作:

import os

@click.command()
@click.option(
    "--username", prompt=True,
    default=lambda: os.environ.get("USER", "")
)
def hello(username):
    click.echo(f"Hello, {username}!")

要描述默认值是什么,请在 show_default .

import os

@click.command()
@click.option(
    "--username", prompt=True,
    default=lambda: os.environ.get("USER", ""),
    show_default="current user"
)
def hello(username):
    click.echo(f"Hello, {username}!")
$ hello --help
Usage: hello [OPTIONS]

Options:
  --username TEXT  [default: (current user)]
  --help           Show this message and exit.

回拨和热切的选择

有时,您需要一个参数来完全更改执行流。例如,当您希望 --version 打印出版本然后退出应用程序的参数。

注:A的实际实现 --version 可重复使用的参数在click as中可用 click.version_option() . 这里的代码只是如何实现这样一个标志的示例。

在这种情况下,您需要两个概念:一个是热切参数,另一个是回调。热切参数是在其他参数之前处理的参数,而回调是在处理参数之后执行的参数。迫切性是必要的,这样较早的必需参数就不会产生错误消息。例如,如果 --version 不急,是个参数 --foo 以前是必需的和定义的,您需要为其指定 --version 工作。有关详细信息,请参阅 回调评估顺序 .

回调是使用三个参数调用的函数:当前 Context ,洋流 Parameter 和价值。上下文提供了一些有用的功能,比如退出应用程序,并允许访问其他已经处理过的参数。

下面是一个示例, --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

是参数

对于危险的操作,能够请求用户确认是非常有用的。这可以通过添加一个布尔值来完成。 --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!')

来自环境变量的值

click的一个非常有用的特性是除了常规参数之外,还可以接受来自环境变量的参数。这使得工具的自动化更加容易。例如,您可能希望传递一个配置文件, --config 参数,也支持导出 TOOL_CONFIG=hello.cfg 关键价值对,以获得更好的发展经验。

点击有两种方式支持这一点。一种方法是自动构建环境变量,而环境变量只支持选项。要启用此功能,请 auto_envvar_prefix 需要将参数传递给调用的脚本。然后将每个命令和参数添加为大写下划线分隔变量。如果有一个子命令调用 run 接受一个被称为 reload 前缀是 WEB ,那么变量是 WEB_RUN_RELOAD .

示例用法:

@click.command()
@click.option('--username')
def greet(username):
    click.echo(f'Hello {username}!')

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

从命令行:

$ export GREETER_USERNAME=john
$ greet
Hello john!

使用时 auto_envvar_prefix 对于命令组,命令名需要包含在环境变量中,在前缀和参数名之间, i.e. PREFIX_COMMAND_VARIABLE . 如果有一个名为 run-server 接受一个被称为 host 前缀是 WEB ,那么变量是 WEB_RUN_SERVER_HOST .

例子:

@click.group()
@click.option('--debug/--no-debug')
def cli(debug):
    click.echo(f"Debug mode is {'on' if debug else 'off'}")

@cli.command()
@click.option('--username')
def greet(username):
    click.echo(f"Hello {username}!")

if __name__ == '__main__':
    cli(auto_envvar_prefix='GREETER')
$ export GREETER_DEBUG=false
$ export GREETER_GREET_USERNAME=John
$ cli greet
Debug mode is off
Hello John!

第二个选项是通过在选项上定义环境变量的名称,从特定的环境变量中手动拉入值。

示例用法:

@click.command()
@click.option('--username', envvar='USERNAME')
def greet(username):
   click.echo(f"Hello {username}!")

if __name__ == '__main__':
    greet()

从命令行:

$ export USERNAME=john
$ greet
Hello john!

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

环境值中的多个值

由于选项可以接受多个值,从环境变量(字符串)中拉入这些值要复杂一些。Click解决此问题的方法是将其保留为自定义此行为的类型。对于两者 multiplenargs 值不是 1 ,Click将调用 ParamType.split_envvar_value() 执行拆分的方法。

所有类型的默认实现是在空白处拆分。此规则的例外是 FilePath 根据操作系统的路径拆分规则拆分的类型。在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(f"writable={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(f"debug={debug}")

if __name__ == '__main__':
    log()

范围选项

这个 IntRange 类型扩展 INT 类型以确保该值包含在给定范围内。这个 FloatRange 类型对 FLOAT .

如果 minmax 省略了,那一边是 无边界 . 该方向上的任何值都可以接受。默认情况下,两个边界都是 关闭 ,即边界值包含在可接受范围内。 min_openmax_open 可用于从该范围排除的范围。

如果 clamp 模式启用时,范围之外的值将设置为边界,而不是失败。例如,范围 0, 5 会回来 5 为了价值 100 为了价值 -1 . 使用时 FloatRangeclamp 仅当两个边界都为 关闭 (默认值)。

@click.command()
@click.option("--count", type=click.IntRange(0, 20, clamp=True))
@click.option("--digit", type=click.IntRange(0, 9))
def repeat(count, digit):
    click.echo(str(digit) * count)
$ repeat --count=100 --digit=5
55555555555555555555
$ repeat --count=6 --digit=12
Usage: repeat [OPTIONS]
Try 'repeat --help' for help.

Error: Invalid value for '--digit': 12 is not in the range 0<=x<=9.

用于验证的回调

Changelog

在 2.0 版本发生变更.

如果要应用自定义验证逻辑,可以在参数回调中执行此操作。如果验证不起作用,这些回调既可以修改值,也可以引发错误。回调在类型转换之后运行。它被调用用于所有来源,包括提示。

在Click 1.0中,只能提升 UsageError 但从click 2.0开始,您还可以提高 BadParameter 错误,这有一个额外的优点,即它将自动格式化错误消息以同时包含参数名。

def validate_rolls(ctx, param, value):
    if isinstance(value, tuple):
        return value

    try:
        rolls, _, dice = value.partition("d")
        return int(dice), int(rolls)
    except ValueError:
        raise click.BadParameter("format must be 'NdM'")

@click.command()
@click.option(
    "--rolls", type=click.UNPROCESSED, callback=validate_rolls,
    default="1d6", prompt=True,
)
def roll(rolls):
    sides, times = rolls
    click.echo(f"Rolling a {sides}-sided dice {times} time(s)")
$ roll --rolls=42
Usage: roll [OPTIONS]
Try 'roll --help' for help.

Error: Invalid value for '--rolls': format must be 'NdM'

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

$ roll
Rolls [1d6]: 42
Error: format must be 'NdM'
Rolls [1d6]: 2d12
Rolling a 12-sided dice 2 time(s)

可选值

向选项提供值可以是可选的,在这种情况下,仅提供选项的标志而不提供值将显示提示或使用其 flag_value .

设置 is_flag=False, flag_value=value 告诉Click仍然可以向该选项传递一个值,但如果只为该标志指定 flag_value 使用。

@click.command()
@click.option("--name", is_flag=False, flag_value="Flag", default="Default")
def hello(name):
    click.echo(f"Hello, {name}!")
$ hello
Hello, Default!
$ hello --name Value
Hello, Value!
$ hello --name
Hello, Flag!

如果选项 prompt 启用,然后设置 prompt_required=False 告诉Click仅在给出选项的标志时才显示提示,而不是在根本没有提供该选项的情况下显示提示。

@click.command()
@click.option('--name', prompt=True, prompt_required=False, default="Default")
def hello(name):
    click.echo(f"Hello {name}!")
$ hello
Hello Default!
$ hello --name Value
Hello Value!
$ hello --name
Name [Default]: 

如果 required=True ,则未给出选项仍会提示,但如果只给出标志也会提示。