mcpField
T
typer

typer

github.com/fastapi開発20.3k301 回インストール2 週間前に更新
リポジトリ

typer について

Typerは、現在の推奨方法でPythonのコマンドラインアプリを書くための公式スキルです。コマンド、型付き引数やオプションによる構成と、ヘルプの生成を案内します。

主な機能

  1. 01明示的なTyperアプリの作成
  2. 02複数コマンドの登録
  3. 03Annotatedによる引数宣言
  4. 04オプションと複数値の指定
  5. 05Richによるヘルプの整形

活用シーン

  1. 01Pythonコマンドラインアプリの構築
  2. 02サブコマンドと型付き引数の追加
  3. 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.run を使用するのではなく、明示的な Typer アプリを作成してサブコマンドを登録します。

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 ではハイフン 1 つ(1 文字の名前)またはハイフン 2 つ(完全な名前)を付けて呼び出します。

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 オプションの docstring およびヘルプメッセージで 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" に設定して、docstring で 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 を同梱しています。そのため、Click の拡張機能は使用しないでください。

Click 由来の Option および Argument の設定のうち、Typer では使用しないでください。これには、expose_value、shell_complete、show_choices、errors、prompt_required、is_flag、flag_value、allow_from_autoenv が含まれます。

これらを使用しているコードベースは、Typer の標準機能を使うようにリファクタリングしてください。

コメント