news 2026/4/25 4:12:25

Python 中的 click 框架

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 中的 click 框架

一、什么是 Click 框架

Click 是 Python 生态中最流行的第三方 CLI 开发框架,由 Flask 作者 Armin Ronacher 开发,核心优势是:

  • 语法简洁(基于装饰器),比 Python 标准库argparse更易上手

  • 支持丰富的功能(子命令、参数验证、颜色输出、提示输入等)

  • 自动生成帮助文档,无需手动编写

  • 跨平台兼容(Windows/Linux/macOS)

二、安装 Click

通过 pip 安装:

pip install click

三、核心使用方法

1. 最简示例:基础命令

先写一个最简单的 CLI 程序,实现 “打招呼” 功能:

import click # @click.command() 把普通函数转为CLI命令 @click.command() def hello(): """这是一个简单的问候命令(帮助信息会自动生成)""" click.echo("Hello, Click!") # click.echo 替代print,兼容多平台 if __name__ == '__main__': hello()

运行效果:

2. 核心功能 1:选项(Option)

@click.option()用于定义可选参数(带---前缀),支持默认值、类型限制、帮助信息等:

import click @click.command() # 定义选项:--name / -n 是参数名,default是默认值,help是帮助信息 @click.option('--name', '-n', default='Guest', help='你的名字') # 定义布尔型选项:--uppercase / -u,is_flag=True 表示是开关(无需传值) @click.option('--uppercase', '-u', is_flag=True, help='是否转为大写') def greet(name, uppercase): """根据输入的名字打招呼""" message = f"Hello, {name}!" if uppercase: message = message.upper() click.echo(message) if __name__ == '__main__': greet()

运行效果

3. 核心功能 2:参数(Argument)

@click.argument()用于定义必选参数(无前缀,直接传值),适合必填的核心参数:

import click @click.command() # 必选参数:filename(无默认值,必须传) @click.argument('filename') # 可选选项:--mode / -m,限制可选值(type=click.Choice) @click.option('--mode', '-m', type=click.Choice(['read', 'write']), default='read', help='操作模式') def file_op(filename, mode): """对指定文件执行操作""" click.echo(f"操作文件:{filename},模式:{mode}") if __name__ == '__main__': file_op()

运行效果

4. 核心功能 3:子命令(Group)

@click.group()用于创建命令组,实现类似git addgit commit这样的子命令结构:

import click # 创建命令组 @click.group() def cli(): """一个包含多个子命令的CLI工具""" pass # 组本身无逻辑,仅用于承载子命令 # 子命令1:hello @cli.command() def hello(): """打招呼""" click.echo("Hello!") # 子命令2:bye @cli.command() @click.option('--name', default='Guest', help='你的名字') def bye(name): """说再见""" click.echo(f"Goodbye, {name}!") if __name__ == '__main__': cli()

运行效果

Click 的group(命令组)设计遵循 CLI 工具的通用范式(比如gitdocker),一次只能执行一个子命令

如果需要一次性执行多个子命令的逻辑,核心思路是:把每个子命令的业务逻辑抽离成普通函数,再新增一个 “批量执行” 的子命令,在里面调用这些普通函数

import click # ---------------------- # 第一步:抽离子命令的核心逻辑为普通函数 # ---------------------- def hello_logic(): """hello子命令的核心逻辑""" click.echo("执行hello逻辑:Hello!") def bye_logic(name="Guest"): """bye子命令的核心逻辑""" click.echo(f"执行bye逻辑:Goodbye, {name}!") # ---------------------- # 第二步:定义命令组和原有子命令(调用抽离的逻辑) # ---------------------- @click.group() def cli(): """支持批量执行多个子命令的CLI工具""" pass # 原有hello子命令(仅调用核心逻辑) @cli.command() def hello(): """单独执行hello""" hello_logic() # 原有bye子命令(仅调用核心逻辑) @cli.command() @click.option('--name', default='Guest', help='你的名字') def bye(name): """单独执行bye""" bye_logic(name) # ---------------------- # 第三步:新增批量执行的子命令 # ---------------------- @cli.command() @click.option('--cmds', '-c', multiple=True, type=click.Choice(['hello', 'bye']), required=True, help='要执行的子命令列表(可多选,比如 -c hello -c bye)') @click.option('--name', default='Guest', help='传给bye的名字参数') def batch(cmds, name): """动态选择批量执行的子命令""" click.echo(f"===== 开始批量执行:{cmds} =====") for cmd in cmds: if cmd == 'hello': hello_logic() elif cmd == 'bye': bye_logic(name) click.echo("===== 批量执行完成 =====") if __name__ == '__main__': cli()

运行效果:

4.1.子命令链式执行

chain=Trueclick.Group的关键参数,作用是允许在一次命令行调用中,按顺序执行多个子命令(即 “链式执行”)。

默认情况下(chain=False,默认值),命令组一次只能执行一个子命令(比如cli hellocli bye);开启chain=True后,可连续执行多个子命令(比如cli hello bye),框架会按输入顺序依次调用每个子命令。

下面是一个极简示例,直观展示chain=True的效果:

import click # 开启链式执行的命令组 @click.group(chain=True) def cli(): """支持链式执行多个子命令的CLI工具""" pass # 子命令1:打招呼 @cli.command() @click.option('--name', default='Guest', help='你的名字') def hello(name): """执行打招呼逻辑""" click.echo(f"[第一步] Hello, {name}!") # 子命令2:说再见 @cli.command() def bye(): """执行说再见逻辑""" click.echo(f"[第二步] Goodbye!") # 子命令3:输出时间 @cli.command() def show_time(): """输出当前时间""" from datetime import datetime now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") click.echo(f"[第三步] 当前时间:{now}") if __name__ == '__main__': cli()

运行效果:

# 链式执行3个子命令
python chain_demo.py hello --name 小明 bye show_time

输出结果(严格按输入顺序执行):

[第一步] Hello, 小明! [第二步] Goodbye! [第三步] 当前时间:2026-02-03 15:30:00

若需要让后续子命令接收前一个子命令的结果,可通过click.pass_context结合上下文的obj属性实现:

import click @click.group(chain=True) @click.pass_context # 传递上下文对象 def cli(ctx): # 初始化上下文存储容器,用于子命令间传值 ctx.ensure_object(dict) ctx.obj['history'] = [] # 存储每个子命令的执行结果 @cli.command() @click.pass_context @click.option('--name', default='Guest') def hello(ctx, name): msg = f"Hello, {name}!" click.echo(msg) ctx.obj['history'].append(msg) # 存入上下文 return msg @cli.command() @click.pass_context def bye(ctx): msg = "Goodbye!" click.echo(msg) ctx.obj['history'].append(msg) # 读取前一个子命令的结果 if len(ctx.obj['history']) >= 2: click.echo(f"← 前一个命令的结果:{ctx.obj['history'][-2]}") if __name__ == '__main__': cli()

运行效果:

python chain_demo.py hello --name 小明 bye

输出:

Hello, 小明! Goodbye! ← 前一个命令的结果:Hello, 小明!

默认情况下,即使某个子命令执行失败,后续子命令仍会执行;如需中断链式执行,可在子命令中主动抛出click.Abort()异常:

@cli.command() def error_demo(): click.echo("这个命令会触发中断!") raise click.Abort() # 中断后续所有子命令

四、实用进阶特性

  1. 提示输入:当用户未传参数时,自动提示输入

    @click.command() @click.option('--name', prompt='请输入你的名字', help='你的名字') def ask_name(name): click.echo(f"你输入的名字是:{name}")
  2. 密码输入:隐藏输入的敏感信息

    @click.command() @click.option('--password', prompt=True, hide_input=True, confirmation_prompt=True) def input_pwd(password): click.echo("密码已输入(已隐藏)")
  3. 颜色输出:让 CLI 输出更美观(需安装 colorama 兼容 Windows)

    pip install colorama
    @click.command() def color_text(): click.echo(click.style("成功", fg="green")) # 绿色文字 click.echo(click.style("警告", fg="yellow", bg="black")) # 黄字黑底 click.echo(click.style("错误", fg="red", bold=True)) # 红色加粗
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 12:36:41

OpenAI RLHF原论文深度解析:一文掌握大模型强化学习PPO算法精髓

本文详细解读OpenAI的RLHF奠基论文,介绍通过三步训练InstructGPT:1)SFT阶段用13k人工标注数据微调GPT-3;2)训练RM模型对response打分;3)使用PPO算法优化LLM。实验表明1.3B参数的InstructGPT效果优于175B GPT-3,文章提供…

作者头像 李华
网站建设 2026/4/22 17:37:37

B帧导致PTS DTS不一致的原理

1. 核心概念DTS(Decoding Time Stamp):解码时间戳,决定「什么时候解码这一帧」,严格遵循解码顺序。PTS(Presentation Time Stamp):显示时间戳,决定「什么时候显示这一帧」…

作者头像 李华
网站建设 2026/4/25 1:25:56

老旧CentOS7服务器JVM加载Jar缓慢排查:竟与NTP服务器有关

老旧CentOS7服务器JVM加载Jar缓慢排查:竟与NTP服务器有关 近期维护一批老旧CentOS 7服务器时,遇到一个十分诡异的JVM故障——使用Java 8加载Jar包时速度异常缓慢,往往要等待数分钟甚至超时,而相同服务器切换到Java 17后&#xff0…

作者头像 李华
网站建设 2026/4/23 7:38:38

Tiez 贴汁 高效的剪贴工具

官方网站 https://tiez.name666.top/zh/ Tiez 贴汁 一贴即合,原汁原味。 不仅是高效的剪贴工具,更是您工作流中值得信赖的“铁汁”。

作者头像 李华
网站建设 2026/4/23 11:38:49

Git-RSCLIP企业级应用:国土调查外业核查前的自动化地物预判

Git-RSCLIP企业级应用:国土调查外业核查前的自动化地物预判 1. 为什么外业核查前需要“预判”? 你有没有遇到过这样的情况:一支国土调查队伍带着设备奔赴几十公里外的田间地头,结果发现——拍回来的照片里,本该是“设…

作者头像 李华
网站建设 2026/4/23 4:33:34

三天,用 AI 写了一个浏览器:真正强大的,还是程序员!

前段时间,Cursor宣布用AI写了一个浏览器FastRender,被全网嘲笑了。这个项目号称使用成百上千个并行 AI 智能体,连续跑了一周,生成了一个Web 浏览器,代码量超过 300 万行。但是很多程序员clone以后,却发现跑…

作者头像 李华