ZetCode

Python Click

最后修改于 2024 年 1 月 29 日

Python Click 教程展示了如何使用 click 模块创建命令行界面。

Python Click

Python click 模块用于创建命令行 (CLI) 应用程序。它是一种易于使用的替代标准 optparse 和 argparse 模块的方法。 它允许任意嵌套命令、自动生成帮助页面,并支持在运行时延迟加载子命令。

click 模块是作为 Flask Web 框架的支持库创建的。

命令是应用程序的基本构建块。 Click 通过装饰器定义命令。 它们使用 click.command 装饰器创建。 值通过选项或参数传递给命令。 选项使用 click.option 装饰器添加,参数使用 click.argument 添加。 选项中的值遵循选项的名称,而参数按位置获取。

$ pip install -U click

我们安装 click 模块。 对于彩色输出,我们还需要 colorama 模块。

Python Click 简单示例

以下是一个简单的 CLI 示例。

simple.py
import click

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


if __name__ == '__main__':
    hello()

该示例创建一个输出消息的命令。

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

Click 使用 echo 而不是 print。 它提高了兼容性并添加了着色支持。

$ ./simple.py 
Hello there
$ ./simple.py --help
Usage: simple.py [OPTIONS]

Options:
  --help  Show this message and exit.

Click 开箱即用地创建一些帮助消息。

Python Click 默认参数

参数使用 click.argument 装饰器添加。 参数可以具有默认值。

argument.py
#!/usr/bin/python

import click


@click.command()
@click.argument('name', default='guest')
def hello(name):
    click.echo(f'Hello {name}')

 
if __name__ == '__main__':
    hello()

该示例使用给定的参数值构建一条消息。 如果没有参数,则使用默认的 guest。 参数作为变量传递给函数。

$ ./argument.py Peter
Hello Peter
$ ./argument.py 
Hello guest

我们使用带和不带参数的程序运行程序。

Python Click 参数类型

我们可以指定参数类型,包括 int、float、str、bool、choice 和各种范围。 默认值为 str。

argument_type.py
#!/usr/bin/python

import click


@click.command()
@click.argument('name', default='guest')
@click.argument('age', type=int)
def hello(name, age):
    click.echo(f'{name} is {age} years old')

 
if __name__ == '__main__':
    hello()

在该示例中,我们有两个参数:name 和 age。 它们按位置生成,第一个是 name,第二个是 age。

$ ./argument_type.py Peter 34
Peter is 34 years old

Python Click 可变数量的参数

使用 nargs 选项,我们可以设置参数采用多个值。 对于 -1 值,该参数可以采用可变数量的值。

variable_args.py
#!/usr/bin/python

import click
from operator import mul
from functools import reduce

@click.command()
@click.argument('vals', type=int, nargs=-1)
def process(vals):

    print(f'The sum is {sum(vals)}')
    print(f'The product is {reduce(mul, vals, 1)}')


if __name__ == '__main__':
    process()

该示例创建一个 process 命令,该命令可以在 vals 参数中采用可变数量的整数值。 该命令计算值的总和和乘积。

$ ./variable_args.py 1 2 3 4 5
The sum is 15
The product is 120

Python Click 简单选项

选项使用 click.option 装饰器添加到命令。 选项名称以一个或两个破折号为前缀。

dots.py
#!/usr/bin/python

import click


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


if __name__ == '__main__':
    dots()

在该示例中,我们有 --n 选项,它接受一个数字。 该数字确定将点打印到控制台的次数。

$ ./dots.py --n 17
.................

我们输出了十七个点。

Python Click 选项名称

选项名称以单个破折号或两个破折号开头。 命令行程序通常采用短选项和长选项。 如果同时使用两者,则 Click 从长名称派生选项的名称。

option_names.py
#!/usr/bin/python

import click


@click.command()
@click.option('-s', '--string')
def output(string):
    click.echo(string)


if __name__ == '__main__':
    output()

在该示例中,我们创建一个具有短名称和长名称的选项。 传递给函数的变量的名称是 string,它源自较长的选项名称。

$ ./option_names.py -s sky
sky
$ ./option_names.py --string cloud
cloud

我们使用两个选项名称运行该程序。

Python Click 提示输入值

我们可以要求用户以交互方式提供值。

prompt.py
#!/usr/bin/python

import click

@click.command()
@click.option("--name", prompt="Your name", help="Provide your name")
def hello(name):
    click.echo(f"Hello, {name}")

if __name__ == '__main__':
    hello()

该示例要求用户提供他的名字。

$ ./prompt.py 
Your name: Peter
Hello, Peter

Python Click 彩色输出

使用 secho 方法,我们可以以颜色输出文本。 我们还可以使用粗体和下划线等样式。 颜色值仅限于预定义的集合。 对于彩色输出,我们需要安装 colorama 模块。

coloured.py
#!/usr/bin/python

import click


@click.command()
def coloured():
    click.secho('Hello there', fg="blue", bold=True)


if __name__ == '__main__':
    coloured()

该示例以粗体蓝色输出文本。

Python Click 标志

标志是可以启用或禁用的布尔选项。 这可以通过一步定义两个标志(用斜杠 (/) 分隔,用于启用或禁用该选项)或使用 is_flag 参数来实现。

flags.py
#!/usr/bin/python

import click


@click.command()
@click.option('--blue', is_flag=True, help='message in blue color')
def hello(blue):

    if blue:
        click.secho('Hello there', fg='blue')
    else:
        click.secho('Hello there')

 
if __name__ == '__main__':
    hello()

在该示例中,我们使用 is_flag 参数定义一个 --blue 布尔选项。 如果设置,它会以蓝色输出消息。

flags2.py
#!/usr/bin/python

import click


@click.command()
@click.argument('word')
@click.option('--shout/--no-shout', default=False)
def output(word, shout):
    if shout:
        click.echo(word.upper())
    else:
        click.echo(word)

if __name__ == '__main__':
    output()

在第二种情况下,我们定义 --shout--no-shout 标志。 如果设置了 --shout 标志,则指定的参数将以大写形式输出。

$ ./flags2.py --shout sky
SKY
$ ./flags2.py --no-shout sky
sky

Python Click 环境变量

可以从环境变量中提取值。

env_var.py
#!/usr/bin/python

import click
import os

@click.argument('mydir', envvar='MYDIR', type=click.Path(exists=True))
@click.command()
def dolist(mydir):

    click.echo(os.listdir(mydir))


if __name__ == '__main__':
    dolist()

该示例打印 MYDIR 环境变量中指定的目录的内容。

export MYDIR=~/Documents; ./env_var.py 
['test.py', 'words2.txt', 'test.php', 'words2.txt~', 'testing', 'todo.txt', 
'tasks', 'links.txt', 'progs']

Python Click 选项元组

我们可以拥有成为 Python 元组的多值选项。

multi_val.py
#!/usr/bin/python

import click


@click.command()
@click.option('--data', required=True, type=(str, int))
def output(data):
    click.echo(f'name={data[0]} age={data[1]}')


if __name__ == '__main__':
    output()

在该示例中,--data 选项采用两个值,这两个值会成为 Python 元组。 这些值用于构建消息。

$ ./multi_val.py --data Peter 23
name=Peter age=23

多次指定选项

可以多次提供选项值,并记录所有值。 这些值存储在 Python 元组中。

multiples.py
#!/usr/bin/python

import click


@click.command()
@click.option('--word', '-w', multiple=True)
def words(word):
    click.echo('\n'.join(word))

if __name__ == '__main__':
    words()

在该示例中,我们可以多次指定 --word/-w 选项。

$ ./multiples.py -w sky --word forest --word rock -w cloud
sky
forest
rock
cloud

click.File 类型

click.File 类型声明一个参数作为用于读取或写入的文件。 一旦上下文关闭(在命令完成工作后),该文件将自动关闭。

words.txt
sky
cloud
water
forest
rock
moon
falcon
lake

我们使用此文本文件。

head.py
#!/usr/bin/python

import click

@click.command()
@click.argument('file_name', type=click.File('r'))
@click.argument('lines', default=-1, type=int)
def head(file_name, lines):

    counter = 0

    for line in file_name:

        print(line.strip())
        counter += 1

        if counter == lines: 
            break


if __name__ == '__main__':
    head()

我们创建一个等效于 Linux head 命令的命令。

$ ./head.py words.txt 4
sky
cloud
water
forest

我们显示该文件的前四行。

click.Path 类型

click.Path 类型类似于 click.File 类型。 它不是返回打开的文件句柄,而是仅返回文件名。

head2.py
#!/usr/bin/python

import click

@click.command()
@click.argument('file_name', type=click.Path(exists=True))
@click.argument('lines', default=-1, type=int)
def head(file_name, lines):

    with open(file_name, 'r') as f:

        counter = 0

        for line in file_name:

            print(line.strip())
            counter += 1

            if counter == lines: 
                break


if __name__ == '__main__':
    head()

这是使用 click.Path 类型创建的 head 命令。

Python Click 命令组

可以将命令添加到组中。 组使用 @click.group 装饰器创建。

groups.py
#!/usr/bin/python

import click


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


@click.command()
def generic():
    click.echo('Hello there')


@click.command()
def welcome():
    click.echo('Welcome')


messages.add_command(generic)
messages.add_command(welcome)


if __name__ == '__main__':
    messages()

该示例定义了两个组。

$ ./groups.py --help
Usage: groups.py [OPTIONS] COMMAND [ARGS]...

Options:
  --help  Show this message and exit.

Commands:
  generic
  welcome

帮助消息显示了两个命令。

groups2.py
#!/usr/bin/python

import click


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


@cli.command(name='gen')
def generic():
    click.echo('Hello there')


@cli.command(name='wel')
def welcome():
    click.echo('Welcome')


if __name__ == '__main__':
    cli()

这是创建命令组的替代语法。 这些命令采用函数的名称,但可以使用 name 选项为其指定另一个名称。

$ ./groups2.py gen
Hello there
$ ./groups2.py wel
Welcome

来源

Python Click 文档

在本文中,我们使用了 Python Click 模块。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程