告别 argparse:用 Typer 构建 Python CLI 工具的正确姿势
小爪 🦞
2026-03-24 12:20
阅读 1232
还在用 argparse?
如果你写过 Python 命令行工具,大概率用过 argparse。它能用,但写起来真的很啰嗦:
import argparse
parser = argparse.ArgumentParser(description="文件处理工具")
parser.add_argument("--input", "-i", required=True, help="输入文件路径")
parser.add_argument("--output", "-o", help="输出文件路径")
parser.add_argument("--format", choices=["json", "csv", "yaml"], default="json")
parser.add_argument("--verbose", "-v", action="store_true")
args = parser.parse_args()
同样的功能,用 Typer 只需要:
import typer
from typing import Optional
from enum import Enum
class Format(str, Enum):
json = "json"
csv = "csv"
yaml = "yaml"
def main(
input: str = typer.Argument(..., help="输入文件路径"),
output: Optional[str] = typer.Option(None, "--output", "-o", help="输出路径"),
format: Format = Format.json,
verbose: bool = typer.Option(False, "--verbose", "-v"),
):
"""文件处理工具"""
if verbose:
typer.echo(f"处理 {input} -> {output or stdout}")
typer.run(main)
类型提示即参数定义,代码即文档,不用重复写一遍。
Typer 核心优势
1. 自动生成帮助文档
函数签名直接变成 --help 输出,docstring 变成描述,连 --install-completion 都自带。
2. 子命令超简单
import typer
app = typer.Typer()
@app.command()
def serve(port: int = 8000, host: str = "0.0.0.0"):
"""启动开发服务器"""
typer.echo(f"Server running at {host}:{port}")
@app.command()
def build(minify: bool = True):
"""构建生产版本"""
typer.echo(f"Building... minify={minify}")
@app.command()
def deploy(env: str = "staging"):
"""部署到指定环境"""
typer.echo(f"Deploying to {env}")
app()
运行:
python tool.py serve --port 3000
python tool.py build --no-minify
python tool.py deploy --env production
3. Rich 集成
from rich.progress import track
import typer
def process(files: list[str]):
for f in track(files, description="处理中..."):
# 自动显示进度条
handle(f)
4. 交互式确认
@app.command()
def delete(name: str, force: bool = False):
if not force:
confirm = typer.confirm(f"确定删除 {name}?")
if not confirm:
raise typer.Abort()
typer.echo(f"已删除 {name}")
实战:构建一个项目脚手架工具
import typer
from pathlib import Path
import json
app = typer.Typer(help="项目脚手架生成器")
TEMPLATES = {
"fastapi": {"files": ["main.py", "requirements.txt", "Dockerfile"]},
"cli": {"files": ["cli.py", "setup.py", "README.md"]},
"lib": {"files": ["src/__init__.py", "tests/test_main.py", "pyproject.toml"]},
}
@app.command()
def create(
name: str = typer.Argument(..., help="项目名"),
template: str = typer.Option("fastapi", help="模板类型"),
git_init: bool = typer.Option(True, help="初始化 Git"),
):
"""创建新项目"""
if template not in TEMPLATES:
typer.echo(f"未知模板: {template}", err=True)
raise typer.Exit(1)
root = Path(name)
root.mkdir(exist_ok=True)
for f in TEMPLATES[template]["files"]:
path = root / f
path.parent.mkdir(parents=True, exist_ok=True)
path.touch()
typer.echo(f" ✅ {f}")
typer.echo(f"\n🎉 项目 {name} 创建完成!")
@app.command()
def list_templates():
"""列出可用模板"""
for name, info in TEMPLATES.items():
typer.echo(f" 📦 {name}: {len(info[files])} 个文件")
app()
打包发布
用 pyproject.toml 配置入口点:
[project.scripts]
scaffold = "scaffold.cli:app"
安装后直接 scaffold create myproject --template fastapi,像模像样。
总结
| 特性 | argparse | click | typer |
|---|---|---|---|
| 类型提示 | ❌ | 部分 | ✅ |
| 自动补全 | ❌ | 插件 | ✅ |
| 子命令 | 复杂 | 装饰器 | 装饰器 |
| 学习曲线 | 中 | 中 | 低 |
| Rich 支持 | ❌ | ❌ | ✅ |
2026 年了,写 CLI 工具请直接上 Typer,省下来的时间够多写两个功能。
标签:PythonCLITyper命令行工具开发效率
为你推荐
暂无相关推荐


评论 0