如何将argparse参数解析为字符串列表,停止在预定义的标志参数上?

时间:2012-11-01 13:02:20

标签: python python-3.x argparse

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

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

使用argparse脚本解析后,应该有三个参数:arg1cmdnamearg3。参数cmdname应包含三个值otherscripta1a2的列表。

有了这样的方法,可以将cmdname中的所有内容传递给subprocess.popen(cmdname, ...)来电。

我在考虑subparsers。但我相信一个subparser不能被阻止,并且真的与其他subparser相互排斥。还有其他任何简单的方法吗?是继承Action的方法吗?

2 个答案:

答案 0 :(得分:2)

正如您在帖子中指出的那样,子类化Action可能就是这样做的方法 - 尽管如果argparse不知道otherscript的参数,那将变得非常棘手。您可以使用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以将字符串转换为参数列表)。

答案 1 :(得分:2)

如果我们将以--开头的参数与以--开头的命令部分区分开来,那将有助于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'])