- 参考链接:
Typer 整体介绍
- Typer 是一款基于 Python 类型注解(Type Hints)的 CLI 开发库,被称为CLI 界的 FastAPI ,是 FastAPI 的同作者开发的“轻兄弟”库
- 理解:Typer(是 CLI 开发库)的本质是将 Python 函数变成可以在 Terminal 直接调用的命令形式
- Typer 基于 Click 构建,兼具代码简洁、自动生成帮助文档、终端自动补全、支持复杂子命令等特性,开发者仅需少量代码就能构建专业、易用的命令行工具,同时对新手极其友好
- 注:Click 是 Python 生态中一款经典、成熟的命令行界面(CLI)开发框架,也是 Typer 的底层核心依赖——Typer 本质上是对 Click 的高级封装,基于 Click 实现了所有 CLI 核心能力,同时通过 Python 类型注解简化了 Click 的使用流程
前置补充:Click 介绍
- Click 由 Pallets 团队开发(同 Flask 开发团队),是 Python 中最主流的 CLI 开发库之一,解决了 Python 内置 argparse 模块代码繁琐、体验不佳、扩展能力弱的问题,核心优势是:
- 基于装饰器实现简洁的命令 / 参数定义
- 原生支持子命令、选项 / 参数解析、终端补全
- 兼容所有主流终端,支持跨平台(Windows/Linux/macOS)
- 提供丰富的扩展能力(如进度条、密码输入、颜色输出)
Typer 核心优势
- 基于 Python 原生类型注解,无需学习新语法,少量代码即可实现 CLI 功能
- 自动生成
--help帮助文档、终端自动补全(支持 Bash/Zsh/Fish/PowerShell),bool 类型参数自动生成--xxx/--no-xxx双选项 - 可灵活扩展,从简单单命令到多层嵌套子命令,可随项目复杂度无缝升级
- 无缝兼容 Python 代码,无需修改现有 Python 脚本,直接通过
typer命令将普通函数转为 CLI 工具 - 内置美观的错误提示(基于 Rich)、进度条、彩色输出,提升用户使用体验
Typer 安装
Typer 支持 Python 3.6+,推荐在虚拟环境中安装,执行以下命令即可:
1
pip install typer
安装完成后会自动附带三个核心依赖:
- Click :Python 经典 CLI 框架,Typer 的底层基础
- Rich :实现美观的格式化输出、彩色错误提示
- shellingham :自动检测当前终端类型,支持自动补全安装
Typer 使用简单示例
无侵入式:普通脚本直接转 CLI
无需在代码中引入 Typer,直接将普通带类型注解的 Python 函数转为 CLI 工具
Step 1,创建
main.py,编写普通函数:1
2
3# 仅需普通Python代码+类型注解,无Typer相关代码
def main(name: str):
print(f"Hello {name}!")Step 2,通过
typer命令运行:1
2
3
4# 查看帮助
typer main.py run --help
# 传入参数运行
typer main.py run 张三Step 3,效果:自动识别
name为必填字符串参数,缺失时会抛出美观的错误提示,无需手动处理参数解析
显式使用(入侵式):引入 Typer 开发
在代码中引入 Typer,可直接通过
python命令运行,更适合正式开发修改
main.py,仅需2行新增代码(导入+运行):1
2
3
4
5
6
7import typer # 新增:导入Typer
def main(name: str):
print(f"Hello {name}!")
if __name__ == "__main__":
typer.run(main) # 新增:运行Typer应用直接通过 Python 运行,体验与原生 CLI 工具一致:
1
2
3
4# 查看帮助
python main.py --help
# 传入参数运行
python main.py 张三
Typer 进阶用法:多子命令开发
- 当 CLI 工具需要多个功能时,Typer 支持通过
@app.command()装饰器创建子命令 ,类似 Git 的git add/git commit模式,结构清晰
基础多子命令代码示例
- 创建包含
hello(问候)和goodbye(告别)两个子命令的工具,goodbye新增布尔可选参数formal(正式模式):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22import typer
# 1. 创建Typer应用实例,作为CLI入口
app = typer.Typer()
# 2. 用@app.command()装饰函数,转为子命令
def hello(name: str):
"""子命令:普通问候"""
print(f"Hello {name}!")
def goodbye(name: str, formal: bool = False):
"""子命令:告别,--formal 开启正式模式"""
if formal:
print(f"Goodbye Ms. {name}. Have a good day!")
else:
print(f"Bye {name}!")
# 3. 运行应用
if __name__ == "__main__":
app()
基础多子命令运行与使用示例
查看全局帮助(显示所有子命令):
1
python main.py --help
- 会自动列出
hello、goodbye两个子命令,以及--install-completion(安装终端补全)等全局选项
- 会自动列出
查看子命令帮助:
1
2# 查看goodbye子命令的帮助,会显示--formal/--no-formal选项
python main.py goodbye --help执行子命令:
1
2
3
4# 普通告别
python main.py goodbye 张三
# 正式模式告别(bool参数自动生成--formal选项)
python main.py goodbye --formal 张三
基础多子命令示例关键特性说明
- 布尔参数自动优化 :定义
formal: bool = False后,Typer 会自动生成--formal(开启)和--no-formal(关闭)两个选项,无需手动配置 - 帮助文档自动生成 :函数的文档字符串(
"""注释""")会自动作为子命令的帮助说明,--help中直接显示 - 命令名省略规则 :仅单个命令时,可直接
python main.py 参数;多个子命令时,必须显式指定子命令名(如python main.py hello 张三)
Typer 核心语法:参数定义
- Typer 完全基于Python 原生类型注解 定义 CLI 参数,无需学习额外的装饰器或语法,支持所有常见类型
基础类型参数
- 直接通过类型注解定义,Typer 自动解析为 CLI 位置参数/选项:
1
2
3
4
5
6
7
8
9
10
11
def demo(
# 必填字符串参数(位置参数)
name: str,
# 可选整数参数,默认值10(选项参数)
age: int = 10,
# 布尔参数,默认False(自动生成--is-adult/--no-is-adult)
is_adult: bool = False
):
# 推荐使用 `typer.echo()` 替代 `print()`,支持彩色输出、跨终端兼容
typer.echo(f"姓名:{name},年龄:{age},是否成年:{is_adult}")
常用参数类型
- 除基础类型外,Typer 还支持以下常用类型,直接注解即可:
- 列表 :
List[str],接收多个参数 - 路径 :
Path,自动校验文件/目录是否存在 - 枚举 :
Enum,实现参数可选值限制 - 文件 :
typer.File(),直接读取文件对象
- 列表 :
- 示例(枚举+列表):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16from typing import List
from enum import Enum
import typer
# 枚举:限制gender的可选值
class Gender(str, Enum):
MALE = "male"
FEMALE = "female"
def user(
name: str,
gender: Gender, # 仅能传入male/female
hobbies: List[str] = None # 接收多个爱好,如--hobbies 篮球 读书
):
typer.echo(f"姓名:{name},性别:{gender},爱好:{hobbies}")
Typer 高级功能:子命令组与全局配置
- 当 CLI 工具功能复杂时,可创建子命令组(如按模块拆分:
db backup/db restore),并通过@app.callback()实现全局配置(如环境、全局参数)
Typer 子命令组示例(数据库工具)
示例代码
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
27import typer
# 全局应用入口
app = typer.Typer(help="多功能CLI工具")
# 创建子命令组:db(数据库相关操作)
db_app = typer.Typer(help="数据库操作子命令组")
# 将子命令组添加到全局应用,命令名为db
app.add_typer(db_app, name="db")
# db子命令组下的子命令:backup(备份)
def backup(path: str = "./backup.db"):
typer.echo(f"正在备份数据库到:{path}")
# db子命令组下的子命令:restore(恢复)
def restore(path: str = "./backup.db"):
typer.echo(f"正在从{path}恢复数据库")
# 全局子命令:无归属,直接在根目录
def version():
typer.echo("CLI工具版本:v1.0.0")
if __name__ == "__main__":
app()运行:
1
2
3
4
5
6# 查看数据库子命令组帮助
python main.py db --help
# 执行数据库备份
python main.py db backup --path D:/mydb.db
# 执行全局版本命令
python main.py version
Typer 全局配置(@app.callback())
通过
@app.callback()定义全局参数(如运行环境env),所有子命令均可共享:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20import typer
from typer import Context
app = typer.Typer(help="带全局配置的CLI工具")
# 全局回调:定义全局参数,所有子命令生效,所有子命令执行前,都会先执行这个函数
def global_config(ctx: Context, env: str = typer.Option("dev", help="运行环境:dev/prod/test")):
# 将全局参数存入ctx,供子命令获取
ctx.ensure_object(dict)
ctx.obj["env"] = env # 注:所有子命令的 ctx 对象都可以传入 env 参数,并可通过 ctx.obj["env"] 获取到 env
def run(ctx: Context):
# 获取全局配置的env
env = ctx.obj["env"]
typer.echo(f"在{env}环境中运行程序...")
if __name__ == "__main__":
app()运行:
1
2
3
4# 用默认dev环境运行
python main.py run
# 指定prod环境运行
python main.py run --env prod
Typer 实用功能:终端补全与进度条
安装终端自动补全
Typer 支持一键安装终端自动补全,输入以下命令后按提示操作即可:
1
python main.py --install-completion
- 支持 Bash、Zsh、Fish、PowerShell 等主流终端,安装后输入命令时按
Tab即可自动补全子命令和参数
- 支持 Bash、Zsh、Fish、PowerShell 等主流终端,安装后输入命令时按
内置进度条
- 处理耗时操作(如下载、批量处理)时,Typer 内置进度条功能,无需额外安装库,一行代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import typer
import time
app = typer.Typer()
def download(total: int = 10):
"""模拟下载,显示进度条"""
# 用 typer.progressbar 创建进度条
with typer.progressbar(range(total), label="下载中") as progress:
for i in progress:
time.sleep(0.5) # 模拟耗时操作
typer.echo("下载完成!")
if __name__ == "__main__":
app()