5

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

论点是这样的:

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

我希望它把它解析成可用的东西,比如位置参数列表和填充默认值的可选参数列表。例如,如果在上面的示例中可选的默认值为 0:

positional = [arg1, arg2, arg3, arg4, arg5]
optional = [0, 1, 2, 0, 0]

换句话说,parser.add_argument('-o', action='append')这不是我想要的,因为我丢失了位置参数,每个可选参数都与之相关联。

4

3 回答 3

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)。

于 2013-01-18T16:15:48.243 回答
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
于 2013-07-28T04:28:19.870 回答
-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。

于 2013-01-18T16:19:14.463 回答