我的程序使用点击进行命令行处理。它有一个主命令,它接受所需的参数。此命令有接受可选参数的子命令。不同的子命令采用不同的选项,但它们都需要来自父命令的相同参数。我希望命令行如下所示:
python myprogram.py argument-value subcommand1 --option-1=value我可以像这样使用Click来写这个
import click
@click.group()
@click.argument("argument")
@click.pass_context
def main(context, argument):
"""ARGUMENT is required for both subcommands"""
context.obj = {"argument": argument}
@click.command()
@click.option("--option-1", help="option for subcommand 1")
@click.pass_context
def subcommand1(context, option_1):
print("subcommand 1: %s %s" % (context.obj["argument"], option_1))
@click.command()
@click.option("--option-2", help="option for subcommand 2")
@click.pass_context
def subcommand2(context, option_2):
print("subcommand 2: %s %s" % (context.obj["argument"], option_2))
main.add_command(subcommand1)
main.add_command(subcommand2)
if __name__ == "__main__":
main()最高级的帮助信息是我想要的。
python myprogram.py --help
Usage: myprogram.py [OPTIONS] ARGUMENT COMMAND [ARGS]...
ARGUMENT is required for both subcommands
Options:
--help Show this message and exit.
Commands:
subcommand1
subcommand2如果我传递所需的参数,我可以获得子命令的帮助。
python myprogram.py dummy-argument subcommand1 --help
Usage: myprogram.py subcommand1 [OPTIONS]
Options:
--option-1 TEXT option for subcommand 1
--help Show this message and exit.但是,我希望获得子命令帮助,而不需要用户传递虚拟参数。我希望能够运行python myprogram.py subcommand1 --help并看到与上面相同的输出,但是我只是获得顶层的帮助文本。
python myprogram.py subcommand1 --help
Usage: myprogram.py [OPTIONS] ARGUMENT COMMAND [ARGS]...
ARGUMENT is required for both subcommands
Options:
--help Show this message and exit.
Commands:
subcommand1
subcommand2有没有办法得到我想要的行为?我意识到Click非常重视它的每个命令都是独立的,但这似乎是一个常见的场景。
发布于 2017-11-22 19:57:02
您的需求中存在固有的模糊性,因为子命令名可能与公共参数的有效值相同。
因此,需要某种方法来消除歧义。我在下面提出一个可能的解决办法。
当找到与子命令名匹配的参数值时,建议的解决方案将搜索是否存在--help。如果找到它,则假定正在为该子命令请求帮助,并将自动填充dummy-argument。
定制类:
import click
class PerCommandArgWantSubCmdHelp(click.Argument):
def handle_parse_result(self, ctx, opts, args):
# check to see if there is a --help on the command line
if any(arg in ctx.help_option_names for arg in args):
# if asking for help see if we are a subcommand name
for arg in opts.values():
if arg in ctx.command.commands:
# this matches a sub command name, and --help is
# present, let's assume the user wants help for the
# subcommand
args = [arg] + args
return super(PerCommandArgWantSubCmdHelp, self).handle_parse_result(
ctx, opts, args)使用自定义类:
要使用自定义类,将cls参数传递给@click.argument()装饰器,如下所示:
@click.argument("argument", cls=PerCommandArgWantSubCmdHelp)这是怎么回事?
这是因为click是一个设计良好的OO框架。@click.argument()装饰器通常实例化一个click.Argument对象,但允许使用cls参数对此行为进行重写。因此,在我们自己的类中继承click.Argument相对容易,而不是使用所需的方法。
在本例中,我们遍历click.Argument.handle_parse_result()并查找子命令名的模式,然后是--help。找到后,我们将修改参数列表,以获得模式单击需要解析的方式来显示子命令帮助。
测试代码:
@click.group()
@click.argument("argument", cls=PerCommandArgWantSubCmdHelp)
@click.pass_context
def main(context, argument):
"""ARGUMENT is required for both subcommands"""
context.obj = {"argument": argument}
@click.command()
@click.option("--option-1", help="option for subcommand 1")
@click.pass_context
def subcommand1(context, option_1):
print("subcommand 1: %s %s" % (context.obj["argument"], option_1))
@click.command()
@click.option("--option-2", help="option for subcommand 2")
@click.pass_context
def subcommand2(context, option_2):
print("subcommand 2: %s %s" % (context.obj["argument"], option_2))
main.add_command(subcommand1)
main.add_command(subcommand2)
if __name__ == "__main__":
commands = (
'subcommand1 --help',
'subcommand2 --help',
'dummy-argument subcommand1 --help',
)
for cmd in commands:
try:
print('-----------')
print('> ' + cmd)
main(cmd.split())
except:
pass测试结果:
-----------
> subcommand1 --help
Backend TkAgg is interactive backend. Turning interactive mode on.
Usage: test.py subcommand1 [OPTIONS]
Options:
--option-1 TEXT option for subcommand 1
--help Show this message and exit.
-----------
> subcommand2 --help
Usage: test.py subcommand2 [OPTIONS]
Options:
--option-2 TEXT option for subcommand 2
--help Show this message and exit.
-----------
> dummy-argument subcommand1 --help
Usage: test.py subcommand1 [OPTIONS]
Options:
--option-1 TEXT option for subcommand 1
--help Show this message and exit. 发布于 2018-08-06 13:32:43
另一种可能的方法是定义一个自定义装饰器,它添加公共参数/选项,并在每个子命令上使用这个装饰符。这样,在发出subcommand --help时,单击将不会请求参数/选项。
点击的GitHub问题295号中列出了一个可能的实现。示例代码显示了如何添加一个通用装饰器,它可以添加不同的-但共享的-选项。然而,它确实解决了OP的问题。
发布于 2021-03-02 19:40:16
我设法做到了
def create(config):
if config is None:
click.echo('ERROR: Configuration File not found!')
main(datalake(create(['--help'])))https://stackoverflow.com/questions/47437472
复制相似问题