Python 3 + Click: CLI参数在从一个命令调用另一个命令时被删除



我使用Python 3.9和Click来构建一个小的命令行接口实用程序,但是我得到了奇怪的错误,特别是当我试图从另一个以同样方式装饰的函数调用一个装饰为@click.command()的函数时。

我已经把我的程序精简到最低限度来解释我的意思。

这是我的程序

import click
@click.group()
def cli():
pass
@click.command()
@click.argument('id')
def outer(id):
print('outer id',id,type(id))
inner(id)  # run inner() from within outer(), pass argument unchanged
@click.command()       # *
@click.argument('id')  # *
def inner(id):
print('inner id',id,type(id))
cli.add_command(outer)
cli.add_command(inner)  # *
if __name__ == '__main__':
cli()

这是我使用innerouter命令运行脚本时的CLI结果:

% python3 test.py inner 123
inner id 123 <class 'str'>
% python3 test.py outer 123
outer id 123 <class 'str'>
Usage: test.py [OPTIONS] ID
Try 'test.py --help' for help.
Error: Got unexpected extra arguments (2 3)
%
有趣的是,当我使用单个字符参数时它可以工作:
% python3 test.py outer 1
outer id 1 <class 'str'>
inner id 1 <class 'str'>
%

如果我注释掉用# *标记的三行,运行outer命令的行为如预期的那样,将id参数传递给inner()而不改变或问题,无论参数的长度:

% python3 test.py outer 123
outer id 123 <class 'str'>
inner id 123 <class 'str'>
%

显然,装饰器在某种程度上混淆了参数。谁能解释一下为什么是这样,以及如何实现传递参数不变的预期行为?也许我错过了一些非常明显的东西?

提前感谢!

使用上下文操作调用其他命令

import click
@click.group()
def cli():
pass
@click.command()
@click.argument('id')
@click.pass_context
def outer(ctx, id):
print('outer id',id,type(id))
ctx.forward(inner)  # run inner(), pass argument unchanged
ctx.invoke(inner, id=id+1) # run inner(), pass modified argument
@click.command()       # *
@click.argument('id')  # *
def inner(id):
print('inner id',id,type(id))
cli.add_command(outer)
cli.add_command(inner)  # *
if __name__ == '__main__':
cli()

最新更新