如何解决单击 - 如何在带有位置参数的命令下嵌套子命令?
我正在将 open source project's CLI 从 argparse 转移到 click。目前该库允许以下CLI usage patterns:
manim file.py Scene1 Scene2 -p -ql
但也适用于子命令(有些带有自己的子命令),如下所示:
manim plugins --list
manim cfg write --level cwd
... and more.
因此,manim
关键字既是访问子命令的一种方式,更重要的是,它是带有位置参数(python 文件)的命令本身。在 argparse 中,确定 manim
关键字后面的文本是子命令还是位置参数是读取 sys.argv[2]
并确定它是否与可用子命令之一匹配的问题,else 这是一个位置参数。结果是添加子命令和大量样板代码需要付出很多努力……因此转换为单击的动作;然而,这种特殊的使用模式似乎并不是在点击时开箱即用的。
换句话说,下面的代码:
@click.group()
@click.argument('file')
def main(file):
print('main',file)
@main.command()
@click.option('--opt')
def subcommand1(opt):
print("sub1",opt)
提出两个问题:
- 需要满足
main
组的位置参数才能运行任何子命令(即main file.py subcommand1
而不是main subcommand1
) - 它不会在没有子命令的情况下执行 Group + 参数(即
main file.py
在没有指定 subommand1 到 Group 的情况下是不可能的)。
经过进一步研究,我使用点击组参数 invoke_without_command
@click.group(invoke_without_command=True)
@click.argument('file')
def main(file):
print('main',opt)
但我仍然面临第一点的问题——选择不使用位置参数而是调用子命令的一般能力。 Stephen Raunch 回答的这个 StackOverflow article 似乎相关;但是,它仅适用于帮助选项,而不适用于参数和选项的更一般用例。
如何允许子命令的任意嵌套,例如 Group,但仍然提供像 @click.command() 那样使用位置参数执行该 Group 的能力?如果这不是推荐的模式,您会推荐什么?
解决方法
在对该主题进行更多研究时,我遇到了这个 stackoverflow article,这导致了这个自定义组的创建:
import click
from click.decorators import pass_context
class SkipArg(click.Group):
def parse_args(self,ctx,args):
if args[0] in self.commands:
if len(args) == 1 or args[1] not in self.commands:
# This condition needs updating for multiple positional arguments
args.insert(0,'')
super(SkipArg,self).parse_args(ctx,args)
@click.group(cls=SkipArg,invoke_without_command=True)
@click.argument('file')
@pass_context
def main(ctx,file):
print('main',file)
@main.command()
@click.option('--opt')
def subcommand1(opt):
print("sub1",opt)
此代码符合使用 click 使命令具有嵌套更多子命令的位置参数的条件。在我将使用点击的情况下,必须针对多个位置参数更新 SkipArg 的逻辑,但作为演示就足够了。
它如何满足标准:
-
main
组用作命令,因为它可以使用invoke_without_command
执行。 - 执行 subcommand1 不需要位置参数,因为类 SkipArg 将
''
插入到参数列表的前面。这是一种硬编码逻辑,当第零个参数与其中一个子命令匹配时,它会为 [FILE] 位置参数应用空填充文本。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。