如何解决使用嵌套子解析器时,Python argparse创建不正确的用法字符串
我想使用模块工具来构建(复杂的)命令行参数解析器。 “主”脚本可以接受子命令,并且某些子命令也具有自己的子命令。这是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()
例程)中,子命令解析器(s1
和s2
的解析器)被添加到{{ 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
。如果不提供,则argparse
从sys.argv[0]
派生,对于子解析器,添加一些字符串以显示子解析器的名称(和必需的主参数)。该添加代码位于add_subparses
和add_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 举报,一经查实,本站将立刻删除。