跳至内容

嵌套子命令

现在我们将看到如何将这些相同的想法扩展到深度嵌套的命令。

让我们想象一下,来自前面示例的同一个CLI 程序现在需要处理lands

但一块土地可以是reigntown

并且它们中的每一个都可以有自己的命令,例如createdelete

用于统治的 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 应用程序中管理土地

现在,让我们将 reignstowns 放在同一个 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()

现在,我们拥有一个单一的 CLI 程序,其中包含一个命令(或命令组)reigns,它有自己的命令。还有一个命令 towns,它有自己的子命令。

检查一下。

// 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.py CLI 程序 中的所有这些命令都应该作为我们之前在第一个示例中构建的 CLI 程序 的一部分。

我们希望我们的 CLI 程序 拥有以下命令/命令组:

  • 用户:
    • 创建
    • 删除
  • 物品:
    • 创建
    • 删除
    • 出售
  • 土地:
    • 统治:
      • 征服
      • 摧毁
    • 城镇:
      • 建立
      • 焚烧

这已经是一个相当深度嵌套的命令/命令组“树”。

但要实现这一点,我们只需要将 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 应用程序添加自动完成功能。