每个位置参数的可选参数

时间:2013-01-18 16:06:30

标签: python argparse

使用argparse(或其他什么?)我希望每个位置参数都有一个带默认值的可选参数。

参数如下:

script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5

我希望它将其解析成可用的东西,比如位置参数列表和可选参数列表,默认值填入。例如如果上例中的Optional的默认值为0:

positional = [arg1, arg2, arg3, arg4, arg5]
optional = [0, 1, 2, 0, 0]
换句话说,parser.add_argument('-o', action='append')不是我想要的,因为我丢失了位置参数,每个可选参数都与之相关联。

3 个答案:

答案 0 :(得分:3)

这是一个简单的黑客,我把它放在一起可能是一个合理的起点:

import argparse

class PositionalAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        lst = getattr(namespace,self.dest)
        lst.append(values)
        parser.last_positional_values = lst
        all_positional = getattr(namespace,'all_positional',[])
        all_positional.append(lst)
        namespace.all_positional = all_positional

class AssociateAction(argparse.Action):
    def __call__(self,parser,namespace,values,option_string=None):
        try:
            parser.last_positional_values.append(values)
        except AttributeError:
            pass

parser = argparse.ArgumentParser()
parser.add_argument('-o',action=AssociateAction,dest=argparse.SUPPRESS)
junk,unknown = parser.parse_known_args()

for i,_ in enumerate(unknown):
    parser.add_argument('arg%d'%i,action=PositionalAction,default=[])

print parser.parse_args()

这就是行动:

temp $ python test1.py foo -o 1 bar -o 2 baz qux -o 4
Namespace(all_positional=[['foo', '1'], ['bar', '2'], ['baz'], ['qux', '4']], arg0=['foo', '1'], arg1=['bar', '2'], arg2=['baz'], arg3=['qux', '4'])

这个问题有一些挑战。首先,你想接受任意数量的位置参数 - argparse不喜欢这样。 argparse想知道预期会发生什么。解决方案是构建一个解析器并解析命令行,但是告诉argparse只解析已知的参数(在这种情况下,非位置-o参数都是静默解析但“位置”参数不是'解析了。) parse_known_args非常适合这种情况,因为它会以(namespace_of_parsed_stuff, uknown_args)的形式返回一个元组。所以现在我们知道了未知的参数 - 我们只需要为解析器添加一个位置参数,以使parse_args满意。

现在,实际上有哪些自定义操作?当找到位置参数时(在第二遍),我们得到默认值(这是一个列表)并将值添加到该列表(此后我将其称为“值”列表)。然后,我们使用对“值”列表的引用来修改解析器。我们还从命名空间中获取“all_positional”列表。如果它没有该属性,我们只得到一个空列表。我们将“value”列表添加到“all_positional”列表并将其放回命名空间。

现在,当我们点击-o标志时,我们会查看解析器以获取“值”列表,然后我们将附加值添加到该列表中。我们可以在不触及解析器的情况下做同样的事情......(我们可以查看namespace.all_positional[-1] - 它与parser.last_positional_values的列表相同。)

答案 1 :(得分:0)

如何直接单步执行sys.argv。您似乎不需要argparse提供的额外功能。例如:

argv='script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5'.split()
pos=[]
opt=[]
i=1
while i<len(argv):
    a=argv[i]
    if a[:2]!='-o':
        pos.append(a)
        opt.append(0)
    else:
        i += 1
        opt[-1]=argv[i]
    i += 1

答案 2 :(得分:-1)

使用optparse,如果有点复杂,它会很强大:

op = optparse.OptionParser(usage=usage)

op.add_option('-c','--cmd',dest='cmd',help="""Command to run. Mutually exclusive with -s. You can use string ${ADDR} to have it replaced with specified host address in the command. """)

op.add_option('-s','--script',dest='script',help="""Script file to run remotely. Mutually exclusive with -c. A script can have its own arguments; specify the whole command in doublequotes, like "script -arg arg".""")

op.add_option('-l','--replicate-owner',dest='replicateowner',action="store_true",help="""Replicate (symbolic) owner and (symbolic) group of the file on the remote host, if possible. If remote account with username the same as local account does not exist on remote host, this will silently fail.""")

# parse cmdline options
(opts, args) = op.parse_args()

opts让你命名args并且args获得位置args。

您可以使用位置参数取值或设置true或false以及更多IIRC。