开发命令行工具的十个 Click 库高级参数

开发
在这篇文章里,我们介绍了利用 Click 构建命令行工具时可以运用到的十个高级特性。

今天就来跟大家聊聊,如何用Click库开发命令行工具的10个高级参数。一步步来,咱们先从简单的开始,再到更高级的功能。

1. 定义基本命令

首先,使用Click库,我们要定义一个最基本的命令。这是一个入门的例子。

# 导入click库
import click

# 定义一个点击装饰器
@click.command()
# 定义函数处理程序逻辑
def hello():
    """简单的命令,输出Hello"""
    click.echo("Hello!")

# 主函数调用
if __name__ == '__main__':
    hello()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

运行输出:

Hello!
  • 1.

这里 click.echo() 是Click推荐使用的打印方式。它比标准 print 更加灵活和强大,尤其是涉及到Unicode或不同平台间的兼容性问题时。

2. 添加简单参数

现在我们往这个简单的命令中加入一个可以输入的名字参数。

import click

@click.command()
@click.argument('name')  # 使用参数
def greet(name):
    """接收name参数,打印个性化问候"""
    click.echo(f"Hello, {name}!")

if __name__ == '__main__':
    greet()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

示例运行:

$ python app.py Alice
Hello, Alice!
  • 1.
  • 2.

这一步中,@click.argument('name') 这句代码,允许命令行后面直接添加参数。

3. 带类型的选项

我们可以给我们的命令行加入更多选择项,并且指定这些项应该是什么样的数据类型。

import click

@click.command()
@click.option('--age', type=int, help="Your age in years.")  # 声明age选项,要求为int类型
def display(age):
    """显示年龄"""
    click.echo(f"Your entered age is: {age}")

if __name__ == '__main__':
    display()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

运行:

$ python app.py --age 26
Your entered age is: 26
  • 1.
  • 2.

这样,通过 --age 参数指定用户的年龄,并在运行时得到反馈。

4. 默认值与帮助文本

接着,让我们看看如何为选项设置默认值和帮助信息,这样可以让用户更容易地了解命令该如何使用。

import click

@click.command()
@click.option('--temperature', default=20, help="Room temperature in degrees Celsius.")
def adjust_temp(temperature):
    """调整温度设置"""
    click.echo(f"The current room temperature is set to: {temperature}°C")

if __name__ == '__main__':
    adjust_temp()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

输出结果(无指定值):

The current room temperature is set to: 20°C
  • 1.

5. 强制用户确认

有些操作可能有破坏性,比如删除文件之类的,那就可以加上用户必须的交互确认了。

import click

@click.command()
@click.confirmation_option(prompt='Are you sure you want to proceed?')
def danger():
    """需要用户确认的操作"""
    click.echo("Action performed!")

if __name__ == '__main__':
    danger()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.

在这个脚本执行时,如果未输入 yes 或 y,则该命令不会生效。

6. 接受多种输入模式的值

如果你有一些选项是可以接受多个值的,比如说颜色列表,也可以很方便实现。

import click

@click.command()
@click.option('--colors', multiple=True, help="List of colors")
def show_colors(colors):
    """展示所有提供的颜色"""
    for color in colors:
        click.echo(f"You chose the color: {color}")

if __name__ == '__main__':
    show_colors()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

运行示例:

$ python app.py --colors red --colors green
You chose the color: red
You chose the color: green
  • 1.
  • 2.
  • 3.

7. 文件读取和写入支持

很多时候命令行需要处理文件输入或者输出。

import click

@click.command()
@click.argument('input_file', type=click.File('r'))
@click.argument('output_file', type=click.File('w'))
def copy(input_file, output_file):
    """拷贝内容至另一文件"""
    output_file.write(input_file.read())
    click.echo('File copied successfully!')

if __name__ == '__main__':
    copy()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

这个脚本将读取第一个文件的内容,将其拷贝到另一个文件。

8. 组合多命令

有时候,一个命令行工具需要很多子命令。比如 git add, git commit 等等。

import click

@click.group()
def cli():
    """主组"""

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

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

if __name__ == '__main__':
    cli()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

在这里使用 @click.group() 可以让我们轻松定义一组子命令。

9. 回调机制与验证

如果需要对用户提供信息进行验证,也可以很容易完成:

import click

def validate_age(ctx, param, value):
    try:
        if value < 0:
            raise ValueError
        return value
    except ValueError:
        raise click.BadParameter('Age must be a non-negative integer.')

@click.command()
@click.option('--age', callback=validate_age, type=int)
def process(age):
    """验证年龄正确性"""
    click.echo(f"Processed your valid age: {age}")

if __name__ == '__main__':
    process()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.

当年龄不是正数或非整数时候将会提示用户错误信息。

10. 实际场景 - 文件查找器

下面是一个综合的小案例,创建一个能够递归搜索特定目录下符合某种扩展名文件的应用程序:

import os
import click

def find_files(dir, ext):
    """实际查找文件方法"""
    results = []
    for dirpath, dirnames, filenames in os.walk(dir):
        for filename in filenames:
            if filename.endswith(ext):
                results.append(os.path.join(dirpath, filename))
    return results

@click.command()
@click.option('-d', '--dir', required=True, type=click.Path(exists=True), help='Directory to search.')
@click.option('-e', '--ext', required=True, help='File extension.')
def finder(dir, ext):
    """命令行应用:寻找扩展名为EXT的文件"""
    files = find_files(dir, ext)
    if not files:
        click.echo('No matching files found.')
    else:
        for file in files:
            click.echo(file)

if __name__ == '__main__':
    finder()
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

这段程序会基于给出的目录和扩展名去寻找相关联的文件,并把它们打印出来。

总结

在这篇文章里,我们介绍了利用Click构建命令行工具时可以运用到的十个高级特性。这些包括但不限于定义基础命令,参数管理,选项配置如指定类型、提供默认值、强制确认、处理多重输入以及文件输入输出功能。还涉及组合型子命令的设计、数据校验回调,最后结合所学到的知识构建了一个实用的小型递归文件搜素器示例。

责任编辑:赵宁宁 来源: 手把手PythonAI编程
相关推荐

2023-04-28 19:44:31

shell脚本命令

2015-09-29 16:03:43

2015-09-28 11:22:55

命令行补全Linux

2023-10-30 01:00:42

Go语言Cobra库

2020-12-10 16:16:08

工具代码开发

2020-12-11 06:44:16

命令行工具开发

2022-07-13 08:21:38

开源命令行工具Linux

2021-01-13 05:29:26

命令行

2022-11-07 16:06:15

TypeScript开发技巧

2022-04-05 00:18:33

工具终端命令行

2019-11-06 19:21:07

Pythonargparse解释器

2019-06-10 15:00:27

node命令行前端

2018-05-04 09:15:35

PythonPlumbum命令行

2021-11-08 10:45:07

Python命令工具

2010-03-10 17:23:37

Python 命令行参

2020-03-30 12:57:50

Linux命令行Markdown

2014-04-09 11:05:11

2019-02-27 09:24:48

命令行文件Linux

2014-02-18 10:45:48

2010-08-24 09:10:14

Linux命令行工具
点赞
收藏

51CTO技术栈公众号