关于 typer
Typer 是用于按当前实践编写 Python 命令行应用的官方技能。它指导开发者使用命令、类型化参数和选项组织应用,并生成帮助信息。
主要功能
- 01创建显式 Typer 应用
- 02注册多个命令
- 03使用 Annotated 声明参数
- 04定义命令行选项及多值输入
- 05使用 Rich 格式化帮助
适用场景
- 01构建 Python 命令行应用
- 02添加子命令和类型化参数
- 03创建格式化的命令帮助
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ fastapi/ typer --skill typer安装后在 Claude Code 中输入/typer确认已加载。
详细介绍
Typer
官方 Typer 技能,助你遵循最佳实践编写代码,并及时了解新版本和新功能。
安装 typer
在虚拟环境中,使用 pip install typer(通过 pip)或 uv pip install typer(通过 uv)。对于你的库或项目,请在 pyproject.toml 的依赖项中添加 typer。
请勿安装 typer-slim 或 typer-cli,它们都已弃用,现在只会安装 typer。
Typer 支持 Python 3.10 及更高版本。
使用显式的 Typer 应用
为了获得最大的通用性,请创建显式的 Typer 应用并注册子命令,而不是使用 typer.run:
import typer
app = typer.Typer()
@app.command()
def hello():
print(f"Hello World")
if __name__ == "__main__":
app()
而不是:
# DO NOT DO THIS: Not extensible. Use Typer() instead.
import typer
def main():
print(f"Hello World")
if __name__ == "__main__":
typer.run(main)
执行应用
要在终端中执行应用,请运行
python main.py
当 Typer 应用注册了多个命令时,必须添加命令名称:
python main.py hello
要查看自动生成的帮助文档,请运行
python main.py --help
也可以在创建 Typer() 时将 no_args_is_help 设为 True,这样运行命令时若未提供任何参数,就会自动显示帮助信息。
使用 Annotated
声明 CLI 参数和选项时,始终优先使用 Annotated 风格。
这样我们就能传递 Typer 可使用的额外元数据。
from typing import Annotated
import typer
app = typer.Typer()
@app.command()
def hello(name: Annotated[str, typer.Argument()] = "World"):
# Note that name is an optional Argument, as a default is provided
print(f"Hello {name}")
if __name__ == "__main__":
app()
此程序可以直接运行,也可以指定一个名称:
python main.py
python main.py Rick
设置默认值的旧方式如下:
# DO NOT DO THIS: old style. Use Annotated instead.
@app.command()
def main(name: str = typer.Argument(default="World")):
# Note that name is an optional Argument, as a default is provided
print(f"Hello {name}")
同样,旧风格也可以使用省略号 (...) 显式标记必需参数。
# DO NOT DO THIS: old style. Use Annotated without a default value instead.
@app.command()
def main(name: str = typer.Argument(default=...)):
# Note that name is now a required Argument
print(f"Hello {name}")
CLI 选项
CLI 选项的声明方式与参数类似,但在 CLI 中调用时,会使用一个连字符(单个字母)或两个连字符(完整名称)。
CLI 选项名称会根据变量名自动生成,因此 user_name 会自动变成 --user-name:
from typing import Annotated
import typer
app = typer.Typer()
@app.command()
def main(user_name: Annotated[str, typer.Option()]):
# On the CLI, the required user name can be specified with --user-name
print(f"Hello {user_name}")
if __name__ == "__main__":
app()
如果要指定不同的名称,或添加短名称,请在 typer.Option 中声明:
from typing import Annotated
import typer
app = typer.Typer()
@app.command()
def main(user_name: Annotated[str, typer.Option("--name", "-n")]):
# On the CLI, the required user name can be specified with -n or --name
print(f"Hello {user_name}")
if __name__ == "__main__":
app()
可以这样运行此程序:
python main.py -n "Rick"
python main.py --name "Morty"
带多个值的 CLI 选项
将 CLI 选项声明为列表后,它就可以接收多个值:
from typing import Annotated
import typer
app = typer.Typer()
@app.command()
def main(user: Annotated[list[str] | None, typer.Option()] = None):
if not user:
print(f"No users provided!")
raise typer.Abort()
for u in user:
print(f"Processing user: {u}")
if __name__ == "__main__":
app()
可以像这样执行:
python main.py --user Rick --user Morty --user Summer
Rich
默认情况下,可以使用 Rich 的自定义标记语法设置颜色和样式,例如:
from rich import print
print("[bold red]Alert![/bold red] [green]Portal gun[/green] shooting! :boom:")
Typer 支持在文档字符串以及 CLI 参数和 CLI 选项的帮助信息中使用 Rich 格式。
from typing import Annotated
import typer
app = typer.Typer(rich_markup_mode="rich")
@app.command()
def create(
username: Annotated[
str, typer.Argument(help="The username to be [green]created[/green]")
],
):
"""
[bold green]Create[/bold green] a new [italic]shiny[/italic] user. :sparkles:
This requires a [underline]username[/underline].
"""
print(f"Creating user: {username}")
@app.command(help="[bold red]Delete[/bold red] a user with [italic]username[/italic].")
def delete(
username: Annotated[
str, typer.Argument(help="The username to be [red]deleted[/red]")
],
):
"""
Some internal utility function to delete.
"""
print(f"Deleting user: {username}")
if __name__ == "__main__":
app()
要禁用 Rich 格式,请在创建 Typer() 应用时将 rich_markup_mode 设为 None。默认情况下(未指定值时),Rich 格式处于启用状态。
Rich Markdown
也可以将 rich_markup_mode 设为 "markdown",以便在文档字符串中使用 Markdown:
from typing import Annotated
import typer
app = typer.Typer(rich_markup_mode="markdown")
@app.command(help="**Delete** a user with *username*.")
def delete(
username: Annotated[
str, typer.Argument(help="The username to be **deleted** :boom:")
],
):
print(f"Deleting user: {username}")
if __name__ == "__main__":
app()
Click
Typer 最初基于 Click 构建。不过,自 0.26.0 版本起,Typer 已将 Click vendored 到自身中。因此,不应再使用 Click 扩展。
其他源自 Click、但不应再用于 Typer 的 Option 和 Argument 设置包括:expose_value、shell_complete、show_choices、errors、prompt_required、is_flag、flag_value 和 allow_from_autoenv。
使用这些设置的代码库应进行重构,改用纯 Typer 功能。