使用嵌套子解析器时,Python argparse创建不正确的用法字符串

如何解决使用嵌套子解析器时,Python argparse创建不正确的用法字符串

我想使用

enter image description here

模块工具来构建(复杂的)命令行参数解析器。 “主”脚本可以接受子命令,并且某些子命令也具有自己的子命令。这是MWE:

#!/usr/bin/env python3
import argparse

def arg_parser():
    parser = argparse.ArgumentParser()

    subparsers = parser.add_subparsers(required=True,dest="cmd")

    p = subparsers.add_parser("c1",help="Command 1")
    p.add_argument("foo",help="foo argument")
    p.add_argument("bar",help="bar argument")
    p.add_argument("-z","--baz",help="baz argument")

    p = subparsers.add_parser("c2",help="Command 2")
    q = p.add_subparsers(required=True,dest="sub_command")

    r = q.add_parser("s1",help="Command 1 - Sub-command 1")
    r.add_argument("arg1",help="first argument")
    r.add_argument("-a","--arg2",help="second argument")

    r = q.add_parser("s2",help="Command 1 - Sub-command 2")

    return parser


def main():
    args = arg_parser().parse_args()

    print(args)

if __name__ == "__main__":
    main()

到目前为止,一切正常,argparse生成的帮助消息看起来正确:

$ ./main.py
usage: main.py [-h] {c1,c2} ...

positional arguments:
  {c1,c2}
    c1        Command 1
    c2        Command 2

optional arguments:
  -h,--help  show this help message and exit

$ ./main.py c2 -h
usage: main.py c2 [-h] {s1,s2} ...

positional arguments:
  {s1,s2}
    s1        Command 1 - Sub-command 1
    s2        Command 1 - Sub-command 2

optional arguments:
  -h,--help  show this help message and exit
$ ./main.py c2 s1 -h
usage: main.py c2 s1 [-h] [-a ARG2] arg1

positional arguments:
  arg1                  first argument

optional arguments:
  -h,--help            show this help message and exit
  -a ARG2,--arg2 ARG2  second argument

现在,我想将长的arg_parser例程拆分为创建解析器的子函数,如下所示:

def sc1_parser():
    r = argparse.ArgumentParser(add_help=False)

    r.add_argument("arg1",help="second argument")

    return r


def c1_parser():
    parser = argparse.ArgumentParser(add_help=None)

    parser.add_argument("foo",help="foo argument")
    parser.add_argument("bar",help="bar argument")
    parser.add_argument("-z",help="baz argument")

    return parser


def c2_parser():

    r = argparse.ArgumentParser(add_help=False)

    q = r.add_subparsers(required=True,dest="sub_command")

    q.add_parser("s1",help="Command 1 - Sub-command 1",parents=[sc1_parser()])
    q.add_parser("s2",help="Command 1 - Sub-command 2")

    return r

def top_parser():
    parser = argparse.ArgumentParser()

    subparsers = parser.add_subparsers(required=True,dest="cmd")

    subparsers.add_parser("c1",help="Command 1",parents=[c1_parser()])
    subparsers.add_parser("c2",help="Command 2",parents=[c2_parser()])

    return parser

(并且显然将对arg_parser()的调用替换为“ top_parser()”)。

但是,在这种情况下,子命令“ s1”和“ s2”的帮助消息不正确:

$ ./main.py -h
usage: main.py [-h] {c1,--help  show this help message and exit
$ ./main.py c2 -h
usage: main.py c2 [-h] {s1,--help  show this help message and exit
$ ./main.py c2 s1 -h
usage: main.py s1 [-h] [-a ARG2] arg1

positional arguments:
  arg1                  first argument

optional arguments:
  -h,--arg2 ARG2  second argument
$ ./main.py c2 s2 -h
usage: main.py s2 [-h]

optional arguments:
  -h,--help  show this help message and exit

知道为什么会这样吗?

我的猜测是,在第一个版本(arg_parse()例程)中,子命令解析器(s1s2的解析器)被添加到{{ 1}}的子解析器方法。但是在第二种情况下,它们被添加到新的“ ArgumentParser”中。

解决方法

如果我添加到您的第一个脚本(在返回之前):

print("progs: ")
print("main: ",parser.prog)
print("   p: ",p.prog)
print("   r: ",r.prog)

运行是:

1319:~/mypy$ python3 stack63361458_0.py c2 s2 -h
progs: 
main:  stack63361458_0.py
   p:  stack63361458_0.py c2
   r:  stack63361458_0.py c2 s2
usage: stack63361458_0.py c2 s2 [-h]

optional arguments:
  -h,--help  show this help message and exit

usage包括prog。如果不提供,则argparsesys.argv[0]派生,对于子解析器,添加一些字符串以显示子解析器的名称(和必需的主参数)。该添加代码位于add_subparsesadd_parser中。

top_parser案件中添加类似的照片

1349:~/mypy$ python3 stack63361458_0.py c2 s2 -h
s2 prog:  stack63361458_0.py s2
top prog:  stack63361458_0.py
c2 prog:  stack63361458_0.py c2
usage: stack63361458_0.py s2 [-h]

optional arguments:
  -h,--help  show this help message and exit

c2获得了预期的prog,但是创建s2.prog时没有“知识”,c2子解析器将调用它。使用parents绕过该链接。

但是我可以为子解析器提供自己的prog

s2 = q.add_parser("s2",help="Command 1 - Sub-command 2",prog=f'MyProg {sys.argv[0]} c2 s2 ')

1358:~/mypy$ python3 stack63361458_0.py c2 s2 -h
s2 prog:  MyProg stack63361458_0.py c2 s2 
top prog:  stack63361458_0.py
c2 prog:  stack63361458_0.py c2
usage: MyProg stack63361458_0.py c2 s2  [-h]

optional arguments:
  -h,--help  show this help message and exit

我们还可以提供自定义usage

我们可以创建parents而不是s2机制来创建c2,然后将其传递给创建其参数的函数:

c2

def c2_parser(q): r = q.add_parser("s1",help="Command 1 - Sub-command 1") r.add_argument("arg1",help="first argument") r.add_argument("-a","--arg2",help="second argument") r = q.add_parser("s2",help="Command 1 - Sub-command 2") 中的

main

p = subparsers.add_parser("c2",help="Command 2") c2_parser(p) 作为向多个子解析器添加相同参数的一种方式(某种程度上)很有用,但在重构较大的内部版本时并不必要。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?