使用 Context
当你创建一个 Typer 应用程序时,它在内部使用 Click。每个 Click 应用程序都有一个称为 "上下文" 的特殊对象,该对象通常是隐藏的。
但是,你可以通过声明类型为 typer.Context
的函数参数来访问上下文。
你可能在 CLI 选项回调和上下文 中读到过。
同样,在命令或主 Typer
回调中,你可以通过声明类型为 typer.Context
的函数参数来访问上下文。
获取上下文¶
例如,假设你希望根据正在调用的子命令在 Typer
回调中执行一些逻辑。
你可以从上下文中获取子命令的名称
import typer
app = typer.Typer()
@app.command()
def create(username: str):
print(f"Creating user: {username}")
@app.command()
def delete(username: str):
print(f"Deleting user: {username}")
@app.callback()
def main(ctx: typer.Context):
"""
Manage users in the awesome CLI app.
"""
print(f"About to execute command: {ctx.invoked_subcommand}")
if __name__ == "__main__":
app()
检查它
$ python main.py create Camila
// We get the message from the callback
About to execute command: create
Creating user: Camila
$ python main.py delete Camila
// We get the message from the callback, this time with delete
About to execute command: delete
Deleting user: Camila
可执行回调¶
默认情况下,回调仅在执行命令之前执行。
并且如果没有提供命令,则显示帮助消息。
但是我们可以使用 `invoke_without_command=True` 即使没有子命令也能运行它
import typer
app = typer.Typer()
@app.command()
def create(username: str):
print(f"Creating user: {username}")
@app.command()
def delete(username: str):
print(f"Deleting user: {username}")
@app.callback(invoke_without_command=True)
def main():
"""
Manage users in the awesome CLI app.
"""
print("Initializing database")
if __name__ == "__main__":
app()
检查它
$ python main.py
// The callback is executed, we don't get the default help message
Initializing database
// Try with a command
$ python main.py create Camila
// The callback is still executed
Initializing database
Creating user: Camila
独占可执行回调¶
如果已经存在要执行的其他命令,我们可能不希望执行回调。
为此,我们可以获取 `typer.Context` 并检查 `ctx.invoked_subcommand` 中是否有调用的命令。
如果它是 `None`,则表示我们没有调用子命令,而是直接调用主程序(回调)
import typer
app = typer.Typer()
@app.command()
def create(username: str):
print(f"Creating user: {username}")
@app.command()
def delete(username: str):
print(f"Deleting user: {username}")
@app.callback(invoke_without_command=True)
def main(ctx: typer.Context):
"""
Manage users in the awesome CLI app.
"""
if ctx.invoked_subcommand is None:
print("Initializing database")
if __name__ == "__main__":
app()
检查它
$ python main.py
// The callback is executed
Initializing database
// Check it with a subcommand
$ python main.py create Camila
// This time the callback is not executed
Creating user: Camila
配置上下文¶
创建命令或回调时,可以传递上下文的配置。
要详细了解可用配置,请查看 Click 的 `Context` 文档。
例如,你可以使用 `ignore_unknown_options` 和 `allow_extra_args` 保留 CLI 程序中未声明的其他 *CLI 参数*。
然后,你可以在 `ctx.args` 中以 `str` 的 `list` 形式访问这些额外的原始 *CLI 参数*。
import typer
app = typer.Typer()
@app.command(
context_settings={"allow_extra_args": True, "ignore_unknown_options": True}
)
def main(ctx: typer.Context):
for extra_arg in ctx.args:
print(f"Got extra arg: {extra_arg}")
if __name__ == "__main__":
app()
$ python main.py --name Camila --city Berlin
Got extra arg: --name
Got extra arg: Camila
Got extra arg: --city
Got extra arg: Berlin
提示
请注意,它将所有额外的 *CLI 参数* 保存为原始 `str` 的 `list`,包括 *CLI 选项* 名称和值,所有内容都放在一起。