Python 命令行工具-Click
命令行工具click的编译指南,仓库地址:https://gitee.com/enzoism/python_cli

1-妇女之友-click
1-脚本代码
python
import click # 导入click库,用于创建命令行界面
@click.command() # 使用click装饰器将函数标记为命令行命令
@click.argument("name") # 定义位置参数name,用户必须提供
@click.option("-a", "--age", type=int, help="你的年龄") # 定义可选参数age,类型为整数,并提供帮助信息
def greet(name, age):
"""一个简单的命令行工具"""
click.echo(f"你好,{name}!") # 使用click.echo输出问候语,比print更兼容
if age: # 如果提供了age参数
click.echo(f"你今年{age}岁了。") # 输出年龄信息
if __name__ == "__main__": # 当脚本直接运行时执行
greet() # 调用greet函数启动命令行程序
2-直接测试
shell
# 基本用法
(base) MacBook-Pro:python_setup_demo rong$ python click_simple.py 张三
你好,张三!
# 带可选参数
(base) MacBook-Pro:python_setup_demo rong$ python click_simple.py 张三 --age 25
你好,张三!
你今年25岁了。
# 查看帮助
(base) MacBook-Pro:python_setup_demo rong$ python click_simple.py --help
Usage: click_simple.py [OPTIONS] NAME
一个简单的命令行工具
Options:
-a, --age INTEGER 你的年龄
--help Show this message and exit.
3-安装测试
shell
# 1-安装包
(base) MacBook-Pro:python_setup_demo rong$ pip install .
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Processing /Users/rong/Documents/EnzoApplication/WorkSpace/Python/20251222_Python_Setup/python_setup_demo02
Preparing metadata (setup.py) ... done
Requirement already satisfied: click>=8.0.0 in /Applications/0ENZO/Installs/anaconda3/anaconda3/lib/python3.10/site-packages (from python-cli-examples==1.0.0) (8.0.4)
Requirement already satisfied: fire>=0.4.0 in /Applications/0ENZO/Installs/anaconda3/anaconda3/lib/python3.10/site-packages (from python-cli-examples==1.0.0) (0.7.1)
Requirement already satisfied: termcolor in /Applications/0ENZO/Installs/anaconda3/anaconda3/lib/python3.10/site-packages (from fire>=0.4.0->python-cli-examples==1.0.0) (3.2.0)
Building wheels for collected packages: python-cli-examples
Building wheel for python-cli-examples (setup.py) ... done
Created wheel for python-cli-examples: filename=python_cli_examples-1.0.0-py3-none-any.whl size=3088 sha256:1e38d417b4c61a60b3acf3ecc8babb938f239f182dbd9b86b67640089ab52861
Stored in directory: /private/var/folders/kt/jy68vj1523dclg3py07q6zxc0000gn/T/pip-ephem-wheel-cache-5u7bw0u5/wheels/3d/19/5b/66b6bb4de747fb17d2199f8aa5945077a5084fa9a196f1092c
Successfully built python-cli-examples
Installing collected packages: python-cli-examples
Successfully installed python-cli-examples-1.0.0
# 2-测试argparse命令
(base) MacBook-Pro:python_setup_demo rong$ argparse-demo 测试用户 --age 30 --city 上海
正在执行 argparse 示例程序...
你好,测试用户!
你今年30岁了。
你正值壮年!
你来自上海
# 3-测试click命令
(base) MacBook-Pro:python_setup_demo rong$ click-demo 张三 --age 25
你好,张三!
你今年25岁了。
# 4-验证两个命令都已安装
(base) MacBook-Pro:python_setup_demo rong$ which argparse-demo
/Applications/0ENZO/Installs/anaconda3/anaconda3/bin/argparse-demo
(base) MacBook-Pro:python_setup_demo rong$ which click-demo
/Applications/0ENZO/Installs/anaconda3/anaconda3/bin/click-demo
# 5-卸载包
(base) MacBook-Pro:python_setup_demo rong$ pip uninstall python-cli-examples
Found existing installation: python-cli-examples 1.0.0
Uninstalling python-cli-examples-1.0.0:
Would remove:
/Applications/0ENZO/Installs/anaconda3/anaconda3/bin/argparse-demo
/Applications/0ENZO/Installs/anaconda3/anaconda3/bin/click-demo
/Applications/0ENZO/Installs/anaconda3/anaconda3/lib/python3.10/site-packages/argparse_01_simple.py
/Applications/0ENZO/Installs/anaconda3/anaconda3/lib/python3.10/site-packages/click_simple.py
/Applications/0ENZO/Installs/anaconda3/anaconda3/lib/python3.10/site-packages/python_cli_examples-1.0.0.dist-info/*
Proceed (Y/n)? y
Successfully uninstalled python-cli-examples-1.0.0
4-Click库优势
相比argparse,Click库具有以下优势:
- 装饰器语法:代码更简洁易读
- 类型提示:自动处理参数类型转换
- 帮助信息:自动生成完整的帮助文档
- 错误处理:内置更好的错误提示
- 可扩展性:支持子命令和复杂的应用结构
5-项目结构更新
python_setup_demo02/
├── setup.py # 包配置文件(已更新支持两个工具)
├── argparse_01_simple.py # argparse示例脚本
├── click_simple.py # click示例脚本
└── BUILD_GUIDE.md # 本编译指南(已更新)
6-支持的所有命令
安装后支持两个命令行工具:
-
argparse-demo: 基于argparse库的演示工具
- 用法:
argparse-demo <name> [options] - 支持: --age, --city, --verbose, --version
- 用法:
-
click-demo: 基于click库的演示工具
- 用法:
click-demo <name> [options] - 支持: --age
- 用法:
7-复杂示例
python
#!/usr/bin/env python3
"""
click 示例脚本
演示如何使用 click 库创建优雅的命令行工具
"""
from datetime import datetime
import click
@click.group(invoke_without_command=True)
@click.pass_context
@click.option('--version', is_flag=True, help='显示版本信息')
def cli(ctx, version):
"""主CLI函数"""
print("正在执行 click 示例程序...")
"""
一个使用 click 创建的命令行工具示例
这是一个功能强大的命令行工具,支持多个子命令。
"""
if version:
click.echo("click_example.py 版本 1.0.0")
return
if ctx.invoked_subcommand is None:
click.echo(ctx.get_help())
@cli.command()
@click.argument('name')
@click.option('-a', '--age', type=int, help='你的年龄')
@click.option('-c', '--city', default='未知', help='你所在的城市')
@click.option('--verbose', is_flag=True, help='显示详细信息')
def greet(name, age, city, verbose):
"""
向用户打招呼的命令
NAME: 要问候的用户名字
"""
click.echo(f"你好,{name}!")
if age:
click.echo(f"你今年{age}岁了。")
# 使用 click 的颜色功能
if age < 18:
click.echo(click.style("你还是个未成年人士!", fg='yellow'))
elif age < 30:
click.echo(click.style("你正处于青壮年时期!", fg='green'))
elif age < 50:
click.echo(click.style("你正值壮年!", fg='blue'))
else:
click.echo(click.style("你已经步入中老年阶段!", fg='magenta'))
click.echo(f"你来自{city}")
if verbose:
click.echo("\n--- 详细信息 ---")
click.echo(f"当前时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
click.echo("感谢使用这个示例程序!")
@cli.command()
@click.option('--count', default=1, help='重复次数')
@click.option('--prefix', default='', help='前缀文本')
@click.argument('message')
def echo(count, prefix, message):
"""
重复输出消息
MESSAGE: 要重复输出的消息
"""
for i in range(count):
click.echo(f"{prefix}{message}")
@cli.command()
@click.option('--length', default=10, help='密码长度')
@click.option('--no-symbols', is_flag=True, help='不使用特殊字符')
def generate_password(length, no_symbols):
"""
生成随机密码
"""
import random
import string
chars = string.ascii_letters + string.digits
if not no_symbols:
chars += "!@#$%^&*"
password = ''.join(random.choice(chars) for _ in range(length))
click.echo(f"生成的密码: {click.style(password, fg='cyan', bold=True)}")
click.echo(f"密码长度: {length}")
click.echo(f"包含特殊字符: {'否' if no_symbols else '是'}")
@cli.command()
@click.argument('filename', type=click.Path(exists=True))
@click.option('--lines', default=10, help='显示的行数')
def tail_file(filename, lines):
"""
显示文件的最后几行
FILENAME: 要读取的文件路径
"""
try:
with open(filename, 'r', encoding='utf-8') as f:
all_lines = f.readlines()
last_lines = all_lines[-lines:] if len(all_lines) > lines else all_lines
click.echo(f"\n文件 {click.style(filename, bold=True)} 的最后 {len(last_lines)} 行:")
click.echo("-" * 50)
for i, line in enumerate(last_lines, 1):
click.echo(f"{i:3d}: {line.rstrip()}")
except Exception as e:
click.echo(click.style(f"错误: {e}", fg='red'), err=True)
if __name__ == '__main__':
cli()
8-标注解释
@click.group
- 用法 :
@click.group(invoke_without_command=True)用于定义一个命令组,它是一个可以包含多个子命令的容器。invoke_without_command=True表示当没有指定子命令时,会调用该命令组对应的函数。 - 示例 :在脚本中,
cli函数被装饰为一个命令组。当用户运行脚本时,如果没有指定子命令,就会执行cli函数中的代码,例如显示帮助信息等。
@click.pass_context
- 用法 :
@click.pass_context用于将上下文对象传递给函数。上下文对象包含了命令行工具运行时的一些信息,如命令行参数、子命令等。 - 示例 :在
cli函数中,通过@click.pass_context装饰器,可以获取到上下文对象ctx,进而可以使用ctx.invoked_subcommand来判断是否有子命令被调用,以及调用ctx.get_help()来获取帮助信息。
@click.option
- 用法 :
@click.option用于定义命令行选项。它有多个参数,如:--version:定义了一个名为version的选项,is_flag=True表示这是一个布尔值选项,当指定该选项时,version的值为True,否则为False。help='显示版本信息'提供了该选项的帮助信息。-a和--age:定义了一个名为age的选项,type=int指定了该选项的值类型为整数,help='你的年龄'提供了帮助信息。-c和--city:定义了一个名为city的选项,default='未知'指定了默认值为'未知',help='你所在的城市'提供了帮助信息。--verbose:定义了一个名为verbose的选项,is_flag=True表示这是一个布尔值选项,help='显示详细信息'提供了帮助信息。--count:定义了一个名为count的选项,default=1指定了默认值为1,help='重复次数'提供了帮助信息。--prefix:定义了一个名为prefix的选项,default=''指定了默认值为空字符串,help='前缀文本'提供了帮助信息。--length:定义了一个名为length的选项,default=10指定了默认值为10,help='密码长度'提供了帮助信息。--no-symbols:定义了一个名为no_symbols的选项,is_flag=True表示这是一个布尔值选项,help='不使用特殊字符'提供了帮助信息。--lines:定义了一个名为lines的选项,default=10指定了默认值为10,help='显示的行数'提供了帮助信息。
- 示例 :在各个命令函数中,通过
@click.option装饰器定义了不同的选项,用户可以在命令行中通过指定这些选项来传递额外的参数,函数根据这些参数的值来执行相应的操作。
@click.argument
- 用法 :
@click.argument用于定义命令行参数。它通常用于指定必须传递的参数。 - 示例 :
- 在
greet函数中,@click.argument('name')定义了一个名为name的参数,表示用户必须在命令行中指定一个名字,否则会报错。 - 在
echo函数中,@click.argument('message')定义了一个名为message的参数,表示用户必须指定一个消息。 - 在
tail_file函数中,@click.argument('filename', type=click.Path(exists=True))定义了一个名为filename的参数,并且通过type=click.Path(exists=True)指定了该参数的类型为路径,并且要求该路径必须存在。如果用户指定的路径不存在,会报错。
- 在
@click.command
- 用法 :
@click.command用于定义一个命令。它将一个函数装饰为一个命令,该函数的名称将成为命令的名称。 - 示例 :在脚本中,
greet、echo、generate_password和tail_file函数都被装饰为命令。用户可以通过指定命令的名称来调用这些函数,例如click_example greet、click_example echo等。
click.echo
- 用法 :
click.echo用于在控制台输出文本。 - 示例 :在脚本中,
click.echo被广泛用于输出各种信息,如问候语、密码、文件内容等。
click.style
- 用法 :
click.style用于对文本进行样式化,例如设置颜色、加粗等。 - 示例 :在脚本中,
click.style被用于给文本添加颜色,如click.style("你还是个未成年人士!", fg='yellow')将文本设置为黄色,click.style(password, fg='cyan', bold=True)将密码文本设置为青色并加粗。
click.Path
- 用法 :
click.Path用于定义路径类型的参数。它可以通过参数指定路径的一些约束条件,如是否存在、是否为文件或目录等。 - 示例 :在
tail_file函数中,type=click.Path(exists=True)指定了filename参数的类型为路径,并且要求该路径必须存在。