0

如何解析由特殊预定义语法分隔的可变长度参数列表。一个例子:

   ./script --arg1 --cmdname otherscript --a1 --a2 --cmdname-- --arg3

用脚本解析后argparse应该有三个参数:arg1, cmdname, arg3. 参数cmdname应包含三个值otherscripta1、的列表a2

拥有这样的配方对于能够将所有内容传递cmdnamesubprocess.popen(cmdname, ...)调用中会很有用。

我在考虑子解析器。但我相信子解析器无法停止,并且与其他子解析器确实是互斥的。还有其他简单的,已经提供的方法吗?子类化Action是这样做的方法吗?

4

2 回答 2

3

如果我们区分以 开头的参数和--同样以 开头的命令部分,这将有助于 argparse --

所以如果./script ++arg1 ++cmdname otherscript --a1 --a2 ++arg3 可以接受,那么:

import argparse
import shlex

parser = argparse.ArgumentParser(prefix_chars = '+')
parser.add_argument('++arg1', action = 'store_true')
parser.add_argument('++arg3', action = 'store_true')
parser.add_argument('++cmdname', nargs = '*')
args = parser.parse_args(shlex.split("++arg1 ++cmdname otherscript --a1 --a2 ++arg3")) 
print(args)

产量

Namespace(arg1=True, arg3=True, cmdname=['otherscript', '--a1', '--a2'])
于 2012-11-01T13:26:01.517 回答
2

正如您在帖子中指出的那样,子类Action化可能是执行此操作的方法——尽管如果otherscriptargparse 不知道参数,这会变得非常棘手。您可能可以使用 来解决此问题parse_known_args,但可能无法解决。老实说,我真的认为最简单的方法是对sys.argv自己进行预处理。

import shlex
s = shlex.split("./script --arg1 --cmdname otherscript --a1 --a2 --cmdname-- --arg3")
def preprocess(lst):
    """
    process an iterable into 2 lists.
    The second list contains the portion bracketed by '--cmdname' and '--cmdname--'
    whereas the first portion contains the rest of it.
    """
    argv1,argv2 = [],[]
    current = argv1
    for i in lst:
        if i == '--cmdname':
           current = argv2
        elif i == '--cmdname--':
           current = argv1
        else:
           current.append(i)
    return argv1,argv2

l1,l2 = preprocess(s)
print l1
print l2

preprocess另一个适用于具有方法的可切片对象的替代实现.index-sys.argv可以正常工作:

def preprocess(lst):
    """
    process an iterable into 2 lists.
    The second list contains the portion bracketed by '--cmdname' and '--cmdname--'
    whereas the first portion contains the rest of it.
    """
    try:
        i1 = lst.index('--cmdname')
        i2 = lst.index('--cmdname--')
        argv1 = lst[i1+1:i2]
        argv2 = lst[:i1]+lst[i2+1:]
    except ValueError:
        argv1 = lst
        argv2 = []

    return argv1,argv2

另一种选择(在@unutbu 的出色评论中指出)是将命令行语法更改为更标准的东西,从而大大简化了问题:

./script --arg1 --cmd "otherscript --a1 --a2" --arg3

cmd然后您可以像通常使用的那样进行解析argparse(指定type=shlex.split此参数以将其从字符串转换为参数列表)。

于 2012-11-01T13:08:45.840 回答