W.P*_*ill 6 python python-click
我的程序使用Click进行命令行处理。它有一个带有必需参数的主命令。此命令具有采用可选参数的子命令。不同的子命令采用不同的选项,但它们都需要来自其父命令的相同参数。我想让命令行看起来像这样:
python myprogram.py argument-value subcommand1 --option-1=value
Run Code Online (Sandbox Code Playgroud)
我可以像这样使用 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()
Run Code Online (Sandbox Code Playgroud)
顶级帮助信息正是我想要的。
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
Run Code Online (Sandbox Code Playgroud)
如果我传入所需的参数,我可以获得子命令的帮助。
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.
Run Code Online (Sandbox Code Playgroud)
但是,我想获得子命令帮助,而无需用户传入虚拟参数。我希望能够运行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
Run Code Online (Sandbox Code Playgroud)
有没有办法获得我想要的行为?我意识到 Click 非常重视让它的每个命令都是独立的,但这似乎是一个常见的场景。
您的要求存在固有的歧义,因为子命令名称可能与公共参数的有效值相同。
因此,需要某种消除歧义的方法。我在下面提出一种可能的解决方案。
当找到与子命令名称匹配的参数值时,建议的解决方案将搜索 是否存在--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)
Run Code Online (Sandbox Code Playgroud)
要使用自定义类,请将cls参数传递给@click.argument()装饰器,如下所示:
@click.argument("argument", cls=PerCommandArgWantSubCmdHelp)
Run Code Online (Sandbox Code Playgroud)
这是可行的,因为 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
Run Code Online (Sandbox Code Playgroud)
-----------
> 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.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2937 次 |
| 最近记录: |