Python argparse,运行一个或多个子命令

时间:2014-08-14 22:34:14

标签: python argparse

我试图编写一个能够执行多个子命令的程序。 argparse模块非常有用,但我认为它缺乏指定多个子命令的能力。例如,如果我有以下代码:

parser = argparse.ArgumentParser(prog='My Prog')
sub_parsers = parser.add_subparsers()

subcommand_a = sub_parsers.add_parser('subcommand_a', help='a help')
subcommand_a.add_argument('req1', help='required argument 1 help')
subcommand_a.add_argument('--opt1', help='option 1 help')
subcommand_a.add_argument('--opt2', nargs='+', help='option 2 help')

subcommand_b = sub_parsers.add_parser('subcommand_b', help='b help')
subcommand_b.add_argument('req1', help='required argument 1 help')
subcommand_b.add_argument('--opt1', help='option 1 help')
subcommand_b.add_argument('--opt2', help='option 2 help')
subcommand_b.add_argument('--opt3', nargs='+', help='option 3 help')

parser.parse_args()

我无法在命令行上同时指定subcommand_a和subcommand_b。我一次只能做其中一个。我想象这需要一个自定义动作,甚至可能是argparse的子类,但我不知道从哪里开始。我希望能够像以下一样调用此程序:

./prog.py subcommand_a FOO --opt1=bar --opt2 1 2 3 -- subcommand_b BAR --opt1='foo' --opt3 a b c --

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

你的问题与几个月前提出的问题基本相同

Multiple invocation of the same subcommand in a single command line

那个想要多次调用相同的子命令,但问题是相同的 - 如何处理多个subparsers参数。

那里的解决方案是将命令行拆分,然后将其分别解析,或者从一次解析中收集“未使用的”部分,以便在第二个或第三个中使用。

这里调整了返回2个命令的代码:

import argparse
parser = argparse.ArgumentParser(prog='My Prog')
sub_parsers = parser.add_subparsers(dest='cmd')

subcommand_a = sub_parsers.add_parser('subcommand_a', help='a help')
subcommand_a.add_argument('req1', help='required argument 1 help')
subcommand_a.add_argument('--opt1', help='option 1 help')
subcommand_a.add_argument('--opt2', nargs=3, help='option 2 help')

subcommand_b = sub_parsers.add_parser('subcommand_b', help='b help')
subcommand_b.add_argument('req1', help='required argument 1 help')
subcommand_b.add_argument('--opt1', help='option 1 help')
subcommand_b.add_argument('--opt2', help='option 2 help')
subcommand_b.add_argument('--opt3', nargs=3, help='option 3 help')

argv = "subcommand_a FOO --opt1=bar --opt2 1 2 3 subcommand_b BAR --opt1=foo --opt3 a b c"
rest = argv.split()
while rest:
    [args, rest] = parser.parse_known_args(rest)
    print args
    print rest

打印:

Namespace(cmd='subcommand_a', opt1='foo', opt2=['1', '2', '3'], req1='FOO')
['subcommand_b', 'BAR', '--opt3', 'a', 'b', 'c']
Namespace(cmd='subcommand_b', opt1=None, opt2=None, opt3=['a', 'b', 'c'], req1='BAR')
[]

我删除了'--'(请参阅我的其他答案的结尾)

我更改了opt2opt3以获取3个参数,而不是变量+。使用+时,无法确定opt2列表的结束位置以及下一个命令的开始位置。

不同的命令采用不同的选项(标志)也很重要。请注意,第一个opt1以第二个值'foo'结束,第二个命令没有。请参阅另一个主题,讨论问题及其解决方法。

答案 1 :(得分:0)

我做了一些测试,并将子命令更改为其他字符串。 如果您使用:

parser = argparse.ArgumentParser(prog='My Prog')
sub_parsers = parser.add_subparsers()

subcommand_a = sub_parsers.add_parser('subcommand_a', help='a help')
subcommand_a.add_argument('req1', help='required argument 1 help')
subcommand_a.add_argument('--opt1', help='option 1 help')
subcommand_a.add_argument('--opt2', nargs='+' help='option 2 help')

subcommand_b = sub_parsers.add_parser('subcommand_b', help='b help')
subcommand_b.add_argument('req1', help='required argument 1 help')
subcommand_b.add_argument('--opt3', help='option 1 help')
subcommand_b.add_argument('--opt4', help='option 2 help')
subcommand_b.add_argument('--opt5', nargs='+', help='option 3 help')

parser.parse_args()

它有效。

我做了一些研究,没有找到一个字符串相等的子命令。文档概述也没有说明。我认为这是一个限制(通过选择)或一个错误。 也许你可以在Source Code Hosting

中查看