跳至内容

Typer 回调

当你创建一个 app = typer.Typer() 时,它作为一个命令组工作。

你可以使用它创建多个命令。

每个命令都可以有自己的CLI 参数

但由于这些CLI 参数由每个命令处理,它们不允许我们为 CLI 应用程序本身创建CLI 参数

但我们可以为此使用 @app.callback()

它非常类似于 @app.command(),但它声明了主 CLI 应用程序的CLI 参数(在命令之前)

import typer

app = typer.Typer()
state = {"verbose": False}


@app.command()
def create(username: str):
    if state["verbose"]:
        print("About to create a user")
    print(f"Creating user: {username}")
    if state["verbose"]:
        print("Just created a user")


@app.command()
def delete(username: str):
    if state["verbose"]:
        print("About to delete a user")
    print(f"Deleting user: {username}")
    if state["verbose"]:
        print("Just deleted a user")


@app.callback()
def main(verbose: bool = False):
    """
    Manage users in the awesome CLI app.
    """
    if verbose:
        print("Will write verbose output")
        state["verbose"] = True


if __name__ == "__main__":
    app()

这里我们使用一个CLI 选项 --verbose 创建一个回调

提示

获取 --verbose 标志后,我们会修改全局状态,并在其他命令中使用它。

还有其他方法可以实现相同的效果,但这对于本示例来说已经足够了。

而且由于我们在回调函数中添加了文档字符串,因此默认情况下它将被提取并用作帮助文本。

检查它

// Check the help
$ python main.py --help

// Notice the main help text, extracted from the callback function: "Manage users in the awesome CLI app."
Usage: main.py [OPTIONS] COMMAND [ARGS]...

  Manage users in the awesome CLI app.

Options:
  --verbose / --no-verbose  [default: False]
  --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:
  create
  delete

// Check the new top level CLI option --verbose

// Try it normally
$ python main.py create Camila

Creating user: Camila

// And now with --verbose
$ python main.py --verbose create Camila

Will write verbose output
About to create a user
Creating user: Camila
Just created a user

// Notice that --verbose belongs to the callback, it has to go before create or delete ⛔️
$ python main.py create --verbose Camila

Usage: main.py create [OPTIONS] USERNAME
Try "main.py create --help" for help.

Error: No such option: --verbose

在创建时添加回调

在创建 typer.Typer() 应用程序时也可以添加回调

import typer


def callback():
    print("Running a command")


app = typer.Typer(callback=callback)


@app.command()
def create(name: str):
    print(f"Creating user: {name}")


if __name__ == "__main__":
    app()

这与使用 @app.callback() 实现的效果相同。

检查它

$ python main.py create Camila

Running a command
Creating user: Camila

覆盖回调

如果你在创建 typer.Typer() 应用程序时添加了回调,则可以使用 @app.callback() 覆盖它

import typer


def callback():
    print("Running a command")


app = typer.Typer(callback=callback)


@app.callback()
def new_callback():
    print("Override callback, running a command")


@app.command()
def create(name: str):
    print(f"Creating user: {name}")


if __name__ == "__main__":
    app()

现在将使用 new_callback()

检查它

$ python main.py create Camila

// Notice that the message is the one from new_callback()
Override callback, running a command
Creating user: Camila

仅为文档添加回调

你还可以添加回调只是为了在文档字符串中添加文档。

它很方便,尤其是在你有多行文本时,因为缩进将自动为你处理

import typer

app = typer.Typer()


@app.callback()
def callback():
    """
    Manage users CLI app.

    Use it with the create command.

    A new user with the given NAME will be created.
    """


@app.command()
def create(name: str):
    print(f"Creating user: {name}")


if __name__ == "__main__":
    app()

现在回调将主要用于提取帮助文本的文档字符串。

检查它

$ python main.py --help

// Notice all the help text extracted from the callback docstring
Usage: main.py [OPTIONS] COMMAND [ARGS]...

  Manage users CLI app.

  Use it with the create command.

  A new user with the given NAME will be created.

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:
  create

// And it just works as normally
$ python main.py create Camila

Creating user: Camila

单击组

如果你来自 Click,此Typer 回调等效于 Click 组 中的函数。

例如

import click

@click.group()
def cli():
    pass

原始函数 cli 等效于 Typer 回调。

技术细节

使用 Click 时,它会将 cli 变量转换为 Click Group 对象。然后原始函数不再存在于该变量中。

Typer 不会这样做,回调函数不会被修改,只会注册在 typer.Typer 应用程序中。这是故意的,这是Typer 设计的一部分,以允许编辑器自动完成和类型检查。