python - 如何在没有 Context.invoke 或 Context.forward 的情况下“自调用”python-click CLI 命令?
问题描述
该click
库不鼓励调用click.forward
和click.forward
函数来“自调用”CLI 命令。引用文档:
有时,从另一个命令调用一个命令可能会很有趣。这是 Click 通常不鼓励使用的模式,但仍有可能。为此,您可以使用 Context.invoke() 或 Context.forward() 方法。
但是,它们不提供替代方案。
例如,假设我们想our_cli get user-funds
在执行假设的our_cli buy some_item
. 不使用Context.invoke
orContext.forward
怎么办?
解决方案
感谢@StephenRauch 提供了直接调用python 代码的提示。
这是一个简化的示例,展示了如何重构Context.invoke
调用以直接调用 python 代码。
例子
假设我们get-user-funds
在购买假设项目之前调用了 CLI 的命令来获取用户的预算。
import click
# E.g., assume the price and funds come from some API
def get_funds(user): return 100
def get_price(item): return 50
@click.group()
@click.pass_context
def our_cli(ctx):
# To simplify, assume that the CLI already knows the relevant user.
ctx.obj = {"user": "Cindy"}
@our_cli.command()
@click.argument("user")
def get_user_funds(user):
# Normally we would use this command to print the funds
# of a user to stdout.
funds = get_funds(user)
click.echo(f"{funds=}")
return funds
@our_cli.command()
@click.argument("item")
@click.pass_context
def buy_item(ctx, item):
# This is the `invoke` call that we wish to refactor.
funds = ctx.invoke(get_user_funds)
if funds >= get_price(item):
print(f"bought {item}")
else:
print("f{funds}")
if __name__ == "__main__":
our_cli()
重构
我们也可以直接调用python代码,而不是调用Context.invoke
获取资金。
我们可以通过buy_item
如下重写来做到这一点:
@our_cli.command()
@click.argument("item")
@click.pass_context
def buy_item(ctx: click.Context, item: str):
# Now we call python code directly.
funds = get_funds(ctx.obj["user"])
# Note that bypass the click.echo(f"{funds=}") call now. This
# is probably something we would like in this example.
if funds >= get_price(item):
print(f"bought {item}")
else:
print("f{funds}")
闭幕致辞
在这个例子中,重构非常简单。
我们已经有了一个get_funds
可以直接调用的python 函数(即)。
在处理更复杂的代码时,您可能必须重新构建代码。
就我而言,除其他外,我必须将我想直接从带@click.command
注释的函数调用的逻辑提取到普通的 python 函数。
之后,我能够Context.invoke
用直接函数调用替换调用。
推荐阅读
- mod-rewrite - URL 重写 - htacces
- reactjs - 使用 react-google-maps 挂载后向 map/clusterer 添加标记
- algorithm - 基于纬度/经度的物流路由和隔离算法
- memory - FilteredListMixin(过滤孩子)
- oracle - 从perl将数字的oracletable传递给存储过程
- powershell - 通过启动进程运行 cmd.exe 但无法将命令传递给 cmd.exe
- .net - dotnet vstest 的 TfsPublisher 记录器
- sql - 选择字符串 MSSQL 的中间部分
- apache-flink - 使用 HA 安装 Apache flink
- tableau-api - 如何在 Tableau 中创建 Web 数据连接器?