ネストされたサブコマンド
ここでは、これらの同じアイデアが、深くネストされたコマンドにどのように拡張できるかを見ていきます。
前の例と同じCLIプログラムが、landsを処理する必要があると仮定しましょう。
ただし、土地はreign(領地)またはtown(町)のいずれかです。
そして、それぞれがcreateやdeleteのような独自のコマンドを持つことができます。
領地のためのCLIアプリ¶
まず、ファイルreigns.pyから始めましょう。
import typer
app = typer.Typer()
@app.command()
def conquer(name: str):
print(f"Conquering reign: {name}")
@app.command()
def destroy(name: str):
print(f"Destroying reign: {name}")
if __name__ == "__main__":
app()
これは、領地を管理するためのシンプルなCLIプログラムです。
// Check the help
$ python reigns.py --help
Usage: reigns.py [OPTIONS] COMMAND [ARGS]...
Options:
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it or customize the installation.
--help Show this message and exit.
Commands:
conquer
destroy
// Try it
$ python reigns.py conquer Cintra
Conquering reign: Cintra
$ python reigns.py destroy Mordor
Destroying reign: Mordor
町のためのCLIアプリ¶
次に、towns.pyで町を管理するための同等のものを作成します。
import typer
app = typer.Typer()
@app.command()
def found(name: str):
print(f"Founding town: {name}")
@app.command()
def burn(name: str):
print(f"Burning town: {name}")
if __name__ == "__main__":
app()
これにより、町を管理できます。
// Check the help
$ python towns.py --help
Usage: towns.py [OPTIONS] COMMAND [ARGS]...
Options:
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it or customize the installation.
--help Show this message and exit.
Commands:
burn
found
// Try it
$ python towns.py found "New Asgard"
Founding town: New Asgard
$ python towns.py burn Vizima
Burning town: Vizima
CLIアプリで土地を管理する¶
次に、reignsとtownsを同じCLIプログラム内のlands.pyにまとめましょう。
import typer
import reigns
import towns
app = typer.Typer()
app.add_typer(reigns.app, name="reigns")
app.add_typer(towns.app, name="towns")
if __name__ == "__main__":
app()
これで、独自のコマンドを持つコマンド(またはコマンドグループ)reignsと、独自のサブコマンドを持つ別のコマンドtownsを持つ単一のCLIプログラムができました。
確認してください
// Check the help
$ python lands.py --help
Usage: lands.py [OPTIONS] COMMAND [ARGS]...
Options:
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it or customize the installation.
--help Show this message and exit.
Commands:
reigns
towns
// We still have the help for reigns
$ python lands.py reigns --help
Usage: lands.py reigns [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
conquer
destroy
// And the help for towns
$ python lands.py towns --help
Usage: lands.py towns [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
burn
found
試してみて、CLIを通して土地を管理してください。
// Try the reigns command
$ python lands.py reigns conquer Gondor
Conquering reign: Gondor
$ python lands.py reigns destroy Nilfgaard
Destroying reign: Nilfgaard
// Try the towns command
$ python lands.py towns found Springfield
Founding town: Springfield
$ python lands.py towns burn Atlantis
Burning town: Atlantis
深くネストされたサブコマンド¶
ここで、lands.pyCLIプログラム内のこれらすべてのコマンドが、最初の例で構築した以前のCLIプログラムの一部である必要があるとします。
CLIプログラムに、以下のコマンド/コマンドグループを持たせたいとします。
users:createdelete
items:createdeletesell
lands:reigns:conquerdestroy
towns:foundburn
これはすでにかなり深くネストされたコマンド/コマンドグループの「ツリー」です。
しかし、これを実現するには、lands Typerアプリを既にあるmain.pyファイルに追加するだけです。
import typer
import items
import lands
import users
app = typer.Typer()
app.add_typer(users.app, name="users")
app.add_typer(items.app, name="items")
app.add_typer(lands.app, name="lands")
if __name__ == "__main__":
app()
これで、すべてが単一のCLIプログラムにまとまりました。
// Check the main help
$ python main.py --help
Usage: main.py [OPTIONS] COMMAND [ARGS]...
Options:
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it or customize the installation.
--help Show this message and exit.
Commands:
items
lands
users
// Try some users commands
$ python main.py users create Camila
Creating user: Camila
// Now try some items commands
$ python main.py items create Sword
Creating item: Sword
// And now some lands commands for reigns
$ python main.py lands reigns conquer Gondor
Conquering reign: Gondor
// And for towns
$ python main.py lands towns found Cartagena
Founding town: Cartagena
ファイルの確認¶
確認/コピーしたい場合は、すべてのファイルがここにあります。
reigns.py:
import typer
app = typer.Typer()
@app.command()
def conquer(name: str):
print(f"Conquering reign: {name}")
@app.command()
def destroy(name: str):
print(f"Destroying reign: {name}")
if __name__ == "__main__":
app()
towns.py:
import typer
app = typer.Typer()
@app.command()
def found(name: str):
print(f"Founding town: {name}")
@app.command()
def burn(name: str):
print(f"Burning town: {name}")
if __name__ == "__main__":
app()
lands.py:
import typer
import reigns
import towns
app = typer.Typer()
app.add_typer(reigns.app, name="reigns")
app.add_typer(towns.app, name="towns")
if __name__ == "__main__":
app()
users.py:
import typer
app = typer.Typer()
@app.command()
def create(user_name: str):
print(f"Creating user: {user_name}")
@app.command()
def delete(user_name: str):
print(f"Deleting user: {user_name}")
if __name__ == "__main__":
app()
items.py:
import typer
app = typer.Typer()
@app.command()
def create(item: str):
print(f"Creating item: {item}")
@app.command()
def delete(item: str):
print(f"Deleting item: {item}")
@app.command()
def sell(item: str):
print(f"Selling item: {item}")
if __name__ == "__main__":
app()
main.py:
import typer
import items
import lands
import users
app = typer.Typer()
app.add_typer(users.app, name="users")
app.add_typer(items.app, name="items")
app.add_typer(lands.app, name="lands")
if __name__ == "__main__":
app()
ヒント
これらのファイルはすべて、if __name__ == "__main__"ブロックを持ち、それぞれが独立したCLIアプリとしてどのように機能するかを示しています。
ただし、最終的なアプリケーションに必要なのは、main.pyだけです。
まとめ¶
以上です。必要に応じて、Typerアプリケーションをいくつでも入れ子にして、簡単なコードを記述しながら複雑なCLIプログラムを作成できます。
おそらく、ここに示す例よりも使いやすい、よりシンプルなCLIプログラムを設計できるでしょう。しかし、要件が複雑な場合、Typerを使用すると、CLIアプリを簡単に構築できます。
ヒント
オートコンプリートは、特に複雑なプログラムでは非常に役立ちます。
CLIアプリにオートコンプリートを追加する方法については、ドキュメントを確認してください。