在单个命令lin中多次调用同一子命令

2024-05-14 16:02:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图找出如何使用argparser执行以下操作:

$ python test.py executeBuild --name foobar1 executeBuild --name foobar2 ....

getBuild本身是一个子命令。我的目标是让脚本能够链接一系列子命令(executeBuild就是其中之一)并按顺序执行它们。在上面的示例中,它将执行一个构建,然后设置环境,然后再次执行构建。如何使用argparse实现这一点?我试过以下方法:

^{pr2}$

但是,似乎每当我这样做时,它就会进入executeBuild的子命令并报告它不知道executeBuild是什么。我试着解析出额外的,这样我就可以执行一个重复调用/链,但是,第一个视图属性似乎已经被覆盖,所以我甚至不能保存额外的选项并遍历。在


Tags: namepytest命令脚本示例目标环境
2条回答

您在问argparse它不是为它编写的:它擅长解析一个命令行(但只能解析一个命令行),而您希望在一行中解析多个命令。IMHO,必须对参数数组进行初始拆分,然后对每个子命令使用argparse。下面的函数接受参数列表(可以是sys.argv),跳过数组中从每个已知子命令开始的第一个参数和剩余的参数。然后可以对每个子列表使用argparse:

def parse(args, subcommands):
    cmds = []
    cmd = None
    for arg in args[1:]:
        if arg in (subcommands):
            if cmd is not None:
                cmds.append(cmd)
            cmd = [arg]
        else:
            cmd.append(arg)
    cmds.append(cmd)
    return cmds

在您的例子中:

^{pr2}$

=>

[['executeBuild', ' name', 'foobar1'], ['executeBuild', ' name', 'foobar2']]

限制:子命令用作保留字,不能用作选项参数。在

在手之前分开sys.argv是一个很好的解决方案。但也可以在使用nargs=argparse.REMAINDER参数进行解析时完成。这种类型的参数获取其余的字符串,不管它们看起来是否像标志。在

parse_known_args替换为以下代码:

...
build_parser.add_argument('rest', nargs=argparse.REMAINDER)
check_parser.add_argument('rest', nargs=argparse.REMAINDER)
extras = 'executeBuild  name foobar1 setupEnv executeBuild  name foobar2'.split()
# or extras = sys.argv[1:]
while extras:
    args = main_parser.parse_args(extras)
    extras = args.rest
    delattr(args,'rest')
    print args
    # collect args as needed

印刷品:

^{pr2}$

在文档中:

argparse.REMAINDER. All the remaining command-line arguments are gathered into a list. This is commonly useful for command line utilities that dispatch to other command line utilities:

REMAINDER的一个问题是太贪心了。http://bugs.python.org/issue14174。因此,build_parser和{}不能有其他位置参数。在


绕过贪婪REMAINDER的方法是使用argparse.PARSER。这是nargs使用的nargs值(未记录)。它类似于REMAINDER,只是第一个字符串必须看起来像一个“参数”(no“-”),并且与choices(如果给定)匹配。PARSER不像{}那么贪婪,因此子parser可以有其他位置参数。在

有一些额外的代码涉及“exit”字符串和伪解析器。这是为了避免PARSER参数是“必需的”(有点像nargs='+'

from argparse import ArgumentParser, PARSER, SUPPRESS

main_parser = ArgumentParser(prog='MAIN')
parsers = {'exit': None}
main_parser.add_argument('rest',nargs=PARSER, choices=parsers)

build_parser = ArgumentParser(prog='BUILD')
parsers['executeBuild'] = build_parser
build_parser.add_argument('cmd')
build_parser.add_argument(' name', action='store', nargs=1, dest='build_name')
build_parser.add_argument('rest',nargs=PARSER, choices=parsers, help=SUPPRESS)

check_parser = ArgumentParser(prog='CHECK')
parsers['setupEnv'] = check_parser
check_parser.add_argument('cmd')
check_parser.add_argument('foo')
check_parser.add_argument('rest',nargs=PARSER, choices=parsers, help=SUPPRESS)

argv = sys.argv[1:]
if len(argv)==0:
    argv = 'executeBuild  name foobar1 setupEnv foo executeBuild  name foobar2'.split()
argv.append('exit') # extra string to properly exit the loop
parser = main_parser
while parser:
    args = parser.parse_args(argv)
    argv = args.rest
    delattr(args,'rest')
    print(parser.prog, args)
    parser = parsers.get(argv[0], None)

样本输出:

('MAIN', Namespace())
('BUILD', Namespace(build_name=['foobar1'], cmd='executeBuild'))
('CHECK', Namespace(cmd='setupEnv', foo='foo'))
('BUILD', Namespace(build_name=['foobar2'], cmd='executeBuild'))

另一种可能是使用' '分隔命令块:

'executeBuild  name foobar1   setupEnv   executeBuild  name foobar2'

但是当有几个' '时,就会出现问题:http://bugs.python.org/issue13922

相关问题 更多 >

    热门问题