返回介绍

选项

发布于 2025-05-06 21:24:11 字数 14530 浏览 0 评论 0 收藏

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

为你的选择命名

命名规则可以在 参数名 . 简而言之,您可以参考该选项 隐含地 由最长的破折号前缀参数:

@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)

基本值选项

最基本的选项是值选项。这些选项接受一个值参数。如果未提供类型,则使用默认值的类型。如果没有提供默认值,则假定类型为 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('from %s to %s' % (from_, 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.

多值选项

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

@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

元组作为多值选项

4.0 新版功能。

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

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

在命令行上:

$ 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):
    click.echo('name=%s id=%d' % item)

多种选择方案

类似于 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

计数

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

@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
LINUX!!!!111
$ info --no-shout
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

请注意,如果选项中已经包含斜线(例如,如果使用 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
LINUX
$ info --lower
linux
$ info
LINUX

选择选项

有时,您希望让一个参数成为一个值列表的选项。在这种情况下,你可以使用 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]
Try "digest --help" for help.

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.

注解

您应该只将选项作为列表或元组传递。其他 iTerables(如发电机)可能会产生令人惊讶的结果。

提示

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

例子:

@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: 

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

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

提示的动态默认值

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

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

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

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

@click.command()
@click.option('--username', prompt=True,
              default=lambda: os.environ.get('USER', ''),
              show_default='current user')
def hello(username):
    print("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 以及价值。上下文提供一些有用的特性,例如退出应用程序,并提供对其他已处理参数的访问。

这里是一个例子 --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

回调签名更改

在 Click 2.0 中,回调的签名已更改。有关这些更改的详细信息,请参阅 升级到 2.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 2.0 中,回调的签名已更改。有关这些更改的详细信息,请参阅 升级到 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!

使用时 auto_envvar_prefix 对于命令组,命令名需要包含在环境变量中,在前缀和参数名之间, i.e. PREFIX_COMMAND_VARIABLE .

例子:

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

@cli.command()
@click.option('--username')
def greet(username):
    click.echo('Hello %s!' % 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('Hello %s!' % 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('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 类型,其工作原理与 INT 类型,但将值限制在特定范围内(包括两边)。它有两种模式:

  • 默认模式(非夹持模式),其中值超出范围将导致错误。
  • 0-5 会回来 5 为了价值 100 为了价值 -1 (例如)。

例子:

@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]
Try "repeat --help" for help.

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。