参数¶
论据的作用类似于 options 但都是位置性的。由于其语法特性,它们也只支持options的一部分特性。Click也不会试图为您记录参数并希望您这样做 document them manually 为了避免难看的帮助页。
基本论点¶
最基本的选项是一个值的简单字符串参数。如果没有提供类型,则使用默认值的类型;如果没有提供默认值,则假定类型为 STRING
.
例子:
@click.command()
@click.argument('filename')
def touch(filename):
"""Print FILENAME."""
click.echo(filename)
看起来像是:
$ touch foo.txt
foo.txt
可变参数¶
第二个最常见的版本是可变参数,其中接受特定(或无限)数量的参数。这可以用 nargs
参数。如果设置为 -1
,则接受无限数量的参数。
然后将值作为元组传递。请注意,只能将一个参数设置为 nargs=-1
因为它会吞噬所有的参数。
例子:
@click.command()
@click.argument('src', nargs=-1)
@click.argument('dst', nargs=1)
def copy(src, dst):
"""Move file SRC to DST."""
for fn in src:
click.echo(f"move {fn} to folder {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/stdout的特殊文件。
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):
"""Copy contents of INPUT to OUTPUT."""
while True:
chunk = input.read(1024)
if not chunk:
break
output.write(chunk)
它的作用是:
$ inout - hello.txt
hello
^D
$ inout hello.txt -
hello
文件路径参数¶
在上一个示例中,文件被立即打开。但是,如果我们只需要文件名呢?天真的方法是使用默认的字符串参数类型。这个 Path
Type有几个可用的检查,如果它们失败了,就会引发很好的错误,比如存在。这些错误消息中的文件名的格式为 format_filename()
,所以任何无法解码的字节都会被很好地打印出来。
例子:
@click.command()
@click.argument('filename', type=click.Path(exists=True))
def touch(filename):
"""Print FILENAME if the file exists."""
click.echo(click.format_filename(filename))
它的作用是:
$ touch hello.txt
hello.txt
$ touch missing.txt
Usage: touch [OPTIONS] FILENAME
Try 'touch --help' for help.
Error: Invalid value for 'FILENAME': Path 'missing.txt' does not exist.
文件打开安全¶
这个 FileType
类型有一个问题需要处理,那就是决定何时打开文件。默认行为是“智能”的。这意味着它将打开stdin/stdout并立即打开要读取的文件。当文件无法打开时,这将给用户直接反馈,但它只会在首次执行IO操作时打开要写入的文件,方法是将文件自动包装在一个特殊的包装器中。
这种行为可以通过传球来强制 lazy=True
或 lazy=False
给建设者。如果文件以延迟方式打开,它将通过引发 FileError
.
由于打开用于写入的文件通常会立即清空该文件,因此只有在开发人员完全确定这是预期行为时,才应禁用惰性模式。
强制惰性模式对于避免资源处理混乱也非常有用。如果文件以惰性模式打开,它将收到 close_intelligently
方法来帮助确定文件是否需要关闭。这对于参数不需要,但对于使用 prompt()
函数,因为您不知道像stdout这样的流是打开的(以前已经打开过)还是需要关闭的真正文件。
从click 2.0开始,还可以通过传递以原子模式打开文件 atomic=True
. 在原子模式下,所有的写操作都将进入同一文件夹中的一个单独的文件中,完成后,文件将移到原始位置。如果修改了其他用户定期读取的文件,则此功能非常有用。
环境变量¶
和选项一样,参数也可以从环境变量中获取值。但是,与选项不同,它只支持显式命名的环境变量。
示例用法:
@click.command()
@click.argument('src', envvar='SRC', type=click.File('r'))
def echo(src):
"""Print value of SRC environment variable."""
click.echo(src.read())
从命令行:
$ export SRC=hello.txt
$ echo
Hello World!
在这种情况下,它也可以是选择第一个环境变量的不同环境变量的列表。
一般来说,不建议使用此功能,因为它会导致用户产生很多混淆。
类选项参数¶
有时,您希望处理看起来像选项的参数。例如,假设您有一个名为 -foo.txt
. 如果以这种方式将其作为参数传递,则Click会将其视为选项。
要解决这个问题,请Click“执行任何POSIX样式的命令行脚本所执行的操作”,即接受字符串 --
作为选项和参数的分隔符。后 --
标记,接受所有其他参数作为参数。
示例用法:
@click.command()
@click.argument('files', nargs=-1, type=click.Path())
def touch(files):
"""Print all FILES file names."""
for filename in files:
click.echo(filename)
从命令行:
$ touch -- -foo.txt bar.txt
-foo.txt
bar.txt
如果你不喜欢 --
marker,您可以将ignore_unknown_options设置为true以避免检查未知选项:
@click.command(context_settings={"ignore_unknown_options": True})
@click.argument('files', nargs=-1, type=click.Path())
def touch(files):
"""Print all FILES file names."""
for filename in files:
click.echo(filename)
从命令行:
$ touch -foo.txt bar.txt
-foo.txt
bar.txt