Typer CLI 框架¶
为什么要学 Typer¶
Typer 是一个用于构建 CLI 应用的 Python 库,由 FastAPI 的作者开发。它利用 Python 类型注解自动生成命令行参数解析、帮助文档和 Shell 自动补全。与 Click 和 argparse 相比,Typer 的代码更简洁、类型安全性更强,开发体验更接近现代 Python 风格。
核心概念¶
| 概念 | 白话解释 | 用途 |
|---|---|---|
| App | 应用 | CLI 应用的主对象 |
| Command | 命令 | 子命令(如 git commit) |
| Argument | 参数 | 必填的位置参数 |
| Option | 选项 | 可选的 --flag 参数 |
| Callback | 回调 | 应用级别的处理(全局选项) |
| Completion | 补全 | Shell Tab 补全 |
安装配置¶
快速上手¶
最简 CLI¶
import typer
def main(name: str):
"""向用户打招呼"""
print(f"Hello {name}")
if __name__ == "__main__":
typer.run(main)
带选项的命令¶
import typer
from typing import Optional
from typing_extensions import Annotated
app = typer.Typer()
@app.command()
def greet(
name: Annotated[str, typer.Argument(help="用户名")],
greeting: Annotated[str, typer.Option(help="问候语")] = "Hello",
count: Annotated[int, typer.Option("--count", "-c", help="重复次数")] = 1,
uppercase: Annotated[bool, typer.Option(help="大写输出")] = False,
):
"""向用户打招呼"""
message = f"{greeting} {name}"
if uppercase:
message = message.upper()
for _ in range(count):
typer.echo(message)
if __name__ == "__main__":
app()
python app.py Alice # Hello Alice
python app.py Alice --greeting "你好" -c 3 # 你好 Alice (3次)
python app.py Alice --uppercase # HELLO ALICE
子命令¶
import typer
app = typer.Typer(help="项目管理工具")
@app.command()
def init(name: str):
"""初始化项目"""
typer.echo(f"初始化项目: {name}")
@app.command()
def build(release: bool = False):
"""构建项目"""
mode = "release" if release else "debug"
typer.echo(f"构建模式: {mode}")
@app.command()
def deploy(env: str = "staging"):
"""部署项目"""
typer.echo(f"部署到: {env}")
if __name__ == "__main__":
app()
进阶用法¶
交互式输入¶
@app.command()
def configure():
name = typer.prompt("项目名称")
password = typer.prompt("密码", hide_input=True)
confirm = typer.confirm("确认创建?")
if confirm:
typer.echo(f"创建项目 {name}")
else:
typer.echo("已取消")
raise typer.Abort()
枚举类型¶
from enum import Enum
class Environment(str, Enum):
dev = "dev"
staging = "staging"
prod = "prod"
@app.command()
def deploy(env: Environment = Environment.staging):
typer.echo(f"部署到 {env.value}")
Rich 集成¶
from rich.console import Console
from rich.table import Table
from rich.progress import track
console = Console()
@app.command()
def status():
table = Table(title="服务状态")
table.add_column("服务", style="cyan")
table.add_column("状态", style="green")
table.add_row("API", "✓ 运行中")
table.add_row("数据库", "✓ 运行中")
table.add_row("缓存", "✗ 已停止")
console.print(table)
@app.command()
def process(files: list[str]):
for file in track(files, description="处理中..."):
import time; time.sleep(0.5)
typer.echo("完成")
命令组嵌套¶
app = typer.Typer()
user_app = typer.Typer(help="用户管理")
app.add_typer(user_app, name="user")
@user_app.command("list")
def user_list():
typer.echo("用户列表")
@user_app.command("create")
def user_create(name: str, email: str):
typer.echo(f"创建用户: {name} ({email})")
版本和回调¶
def version_callback(value: bool):
if value:
typer.echo("v1.0.0")
raise typer.Exit()
@app.callback()
def main(
version: Annotated[
Optional[bool],
typer.Option("--version", "-v", callback=version_callback)
] = None,
verbose: bool = False,
):
"""我的 CLI 工具"""
if verbose:
typer.echo("详细模式已开启")
自动补全安装¶
常见问题¶
Q: 与 Click 的关系?¶
Typer 基于 Click 构建,但用类型注解替代了装饰器参数。如果需要 Click 的高级功能,可以混合使用。
Q: 如何打包为独立命令?¶
Q: 如何处理文件参数?¶
from pathlib import Path
@app.command()
def process(
input_file: Path = typer.Argument(..., exists=True, readable=True),
output_file: Path = typer.Option("output.txt"),
):
content = input_file.read_text()
output_file.write_text(content.upper())
参考资源¶
- GitHub:https://github.com/tiangolo/typer
- 文档:https://typer.tiangolo.com/
- 教程:https://typer.tiangolo.com/tutorial/
- Click 文档:https://click.palletsprojects.com/