在 Python 中,单击如何查看父命令具有必需参数的子命令的 --help?

2023-11-27

我的程序使用Click用于命令行处理。它有一个带有必需参数的主命令。该命令具有带有可选参数的子命令。不同的子命令采用不同的选项,但它们都需要来自其父命令的相同参数。我希望命令行看起来像这样:

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 非常重视其每个命令的独立性,但这似乎是一个常见的情况。


您的要求存在固有的歧义,因为子命令名称可能与公共参数的有效值相同。

因此,需要某种消除歧义的方法。我在下面提出一种可能的解决方案。

当找到与子命令名称匹配的参数值时,建议的解决方案将搜索是否存在--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.                
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 中,单击如何查看父命令具有必需参数的子命令的 --help? 的相关文章

  • 如何恢复tensorflow inceptions检查点文件(ckpt)?

    I have inception resnet v2 2016 08 30 ckpt文件是预先训练的初始模型 我想使用恢复这个模型 saver restore sess ckpt filename 但为此 我将需要编写训练该模型时使用的变量
  • 如何替换 Pandas Dataframe 中不在列表中的所有值? [复制]

    这个问题在这里已经有答案了 我有一个值列表 如何替换 Dataframe 列中不在给定值列表中的所有值 例如 gt gt gt df pd DataFrame D ND D garbage columns S gt gt gt df S 0
  • Pandas set_levels,如何避免标签排序?

    我使用时遇到问题set levels多索引 from io import StringIO txt Name Height Age Metres A 1 25 B 95 1 df pd read csv StringIO txt heade
  • Gunicorn 工作人员无论如何都会超时

    我正在尝试通过gunicorn运行一个简单的烧瓶应用程序 但是无论我做什么 我的工作人员都会超时 无论是否有针对应用程序的活动 工作人员在我设置任何内容后总是会超时timeout值到 是什么导致它们超时 当我发出请求时 请求成功通过 但工作
  • 如何在 Matplotlib 饼图周围绘制箭头以将每个标签指向圆圈中各自的部分?

    我一直在用 Matplotlib 绘制一些图表 我有一个饼图 想要在图表周围绘制箭头 使每个标签都指向图表 我有一个例子 这是我当前的代码 import matplotlib pyplot as plt plt rcParams font
  • 多输出堆叠回归器

    一次性问题 我正在尝试构建一个多输入堆叠回归器 添加到 sklearn 0 22 据我了解 我必须结合StackingRegressor and MultiOutputRegressor 经过多次尝试 这似乎是正确的顺序 import nu
  • 我应该使用 Python 双端队列还是列表作为堆栈? [复制]

    这个问题在这里已经有答案了 我想要一个可以用作堆栈的 Python 对象 使用双端队列还是列表更好 元素数量较少还是数量较多有什么区别 您的情况可能会根据您的应用程序和具体用例而有所不同 但在一般情况下 列表非常适合堆栈 append is
  • 嵌套列表的重叠会产生不必要的间隙

    我有一个包含三个列表的嵌套 这些列表由 for 循环填充 并且填充由 if 条件控制 第一次迭代后 它可能类似于以下示例 a 1 2 0 0 0 0 0 0 4 5 0 0 0 0 0 0 6 7 根据条件 它们不重叠 在第二次迭代之后 新
  • 更好地相当于这个疯狂的嵌套 python for 循环

    for a in map for b in map a for c in map b for d in map c for e in map d print a b c d e 上面的代码用于创建图中一定长度的所有路径 map a 表示从
  • PyQt 使用 ctrl+Enter 触发按钮

    我正在尝试在我的应用程序中触发 确定 按钮 我当前尝试的代码是这样的 self okPushButton setShortcut ctrl Enter 然而 它不起作用 这是有道理的 我尝试查找一些按键序列here http ftp ics
  • 矩形函数的数值傅里叶变换

    本文的目的是通过一个众所周知的分析傅里叶变换示例来正确理解 Python 或 Matlab 上的数值傅里叶变换 为此 我选择矩形函数 这里报告了它的解析表达式及其傅立叶变换https en wikipedia org wiki Rectan
  • GUI(输入和输出矩阵)?

    我需要创建一个 GUI 将数据输入到矩阵或表格中并读取此表单数据 完美的解决方案是限制输入表单仅允许float 例如 A 1 02 0 25 0 30 0 515 0 41 1 13 0 15 1 555 0 25 0 14 1 21 2
  • 如何使用 Selenium 和 ChromeDriver 解决 TypeError: 'module' object is not callable 错误 [重复]

    这个问题在这里已经有答案了 代码试验 from selenium import webdriver from selenium webdriver chrome options import Options as Chromeoptions
  • Java 和 Python 可以在同一个应用程序中共存吗?

    我需要一个 Java 实例直接从 Python 实例数据存储中获取数据 我不知道这是否可能 数据存储是否透明 唯一 或者每个实例 如果它们确实可以共存 都有其单独的数据存储 总结一下 Java 应用程序如何从 Python 应用程序的数据存
  • 使用 python/numpy 重塑数组

    我想重塑以下数组 gt gt gt test array 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43 44 为了得到 gt gt gt test2 array 11 12 21 22 13 14
  • 无法导入 langchain.agents.load_tools

    我正在尝试使用 LangChain Agents 但无法导入 load tools 版本 langchain 0 0 27 我尝试过这些 from langchain agents import initialize agent from
  • 嵌套作用域和 Lambda

    def funct x 4 action lambda n x n return action x funct print x 2 prints 16 我不太明白为什么2会自动分配给n n是返回的匿名函数的参数funct 完全等价的定义fu
  • 找到一个数字所属的一组范围

    我有一个 200k 行的数字范围列表 例如开始位置 停止位置 该列表包括除了非重叠的重叠之外的所有类型的重叠 列表看起来像这样 3 5 10 30 15 25 5 15 25 35 我需要找到给定数字所属的范围 并对 100k 个数字重复该
  • 在virtualenv中下载sqlite3

    我正在尝试使用命令创建应用程序python3 manage py startapp webapp但我收到一条错误消息 django core exceptions ImproperlyConfigured 加载时出错 pysqlite2 或
  • 将索引与值交换的最快方法

    考虑pd Series s s pd Series list abcdefghij list ABCDEFGHIJ s A a B b C c D d E e F f G g H h I i J j dtype object 交换索引和值并

随机推荐