如何正确使用argparse子命令解析器?

79
我已经在这里和其他地方搜索了许多子解析器示例,但似乎无法弄清楚这个看似简单的问题。
我有两种变量类型,其中一种有约束条件,因此认为子解析器是合适的选择。例如,-t 允许使用"A"或"B"。如果用户传递"A",则进一步需要指定它是"a1"还是"a2"。如果他们只传递"B"则不需要。
我能做到这一点吗,并让argparse返回传递的"A"类型或是否只传递了"B"?
以下似乎可以工作,但由于某种原因在通过子解析后传递任何内容时会出现错误。
例如,在linux终端中:
>> python test01.py -t A a1 -v 61

出现错误...

usage: test01.py a1 [-h]
test01.py a1: error: unrecognized arguments: -v

希望这有意义。
代码:
import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='types of A')

parser.add_argument("-t",
                    choices = ["A", "B"],
                    dest = "type",
                    required=True,
                    action='store',
                    help="Some help blah blah")

cam_parser = subparsers.add_parser('a1', help='Default')
cam_parser.set_defaults(which='a1')

cam_parser = subparsers.add_parser('a2', help='parse this instead of default')
cam_parser.set_defaults(which='a2')


parser.add_argument("-v",
                    nargs = '+',
                    required=True,
                    dest = "version",
                    type=int,
                    action='store',
                    help="some version help blah blah")   

argument = parser.parse_args()

print argument.type
print argument.version
1个回答

89

子解析器是根据第一个 位置 参数的值来调用的,因此您的调用将类似于:

python test01.py A a1 -v 61

“A”触发适当的子解析器,该子解析器将被定义为允许位置参数和-v选项。

由于argparse不会强制执行任何关于参数和选项出现顺序的限制,并且在解析开始后没有简单的方法来修改可能出现的参数/选项(涉及修改解析器实例的自定义操作可能有效),因此您应该考虑替换-t本身:

import argparse

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(help='types of A')
parser.add_argument("-v", ...)

a_parser = subparsers.add_parser("A")
b_parser = subparsers.add_parser("B")

a_parser.add_argument("something", choices=['a1', 'a2'])

-v 是为主解析器定义的选项,因此必须在指定用于其余参数的子解析器的参数之前指定。


1
非常感谢您的帮助。但是,当我传递-v参数时,出现了错误,即它期望-v参数,但是当我传递它时,我得到了旧的错误“无法识别的参数”。即使我在位置参数之前传递它也是如此。有什么想法吗?我一直在尝试找到类似的例子,但运气不太好。 - user1571144
“before the argument that specifies which subparser” 是指用户输入参数的代码还是两者都包括? - Nickpick
执行 group1 = parser.add_subparsers(help='subparser group 1')group2 = parser.add_subparsers(help='subparser group 2') 时出现了 error:cannot have multiple subparser arguments 错误。我希望使用它来分组子命令。 - Minh Tran
1
@MinhTran 在这种情况下,您需要使用 a_parser.add_subparsers()b_parser.add_subparsers() - chepner
@chepner,我找不到一个好的例子来说明如何根据传递的参数执行代码。通常使用单个解析器,我会有args = parser.parse_args(),然后类似于if args.thing: <do thing>这样的语句,但是对于子解析器,这个过程并不清晰。 - baxx
argparse文档的这一部分最后展示了一个例子,根据提供的子命令执行一个函数或另一个函数。 - chepner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接