使用argparse(或其他什么?)我希望每个位置参数都有一个带默认值的可选参数.
争论如下:
script.py arg1 arg2 -o 1 arg3 -o 2 arg4 arg5
Run Code Online (Sandbox Code Playgroud)
我希望它将其解析成可用的东西,比如位置参数列表和填充默认值的可选参数列表.例如,如果上例中的Optional的默认值为0:
positional = [arg1, arg2, arg3, arg4, arg5]
optional = [0, 1, 2, 0, 0]
Run Code Online (Sandbox Code Playgroud)
换句话说,parser.add_argument('-o', action='append')不是我想要的,因为我失去了位置参数,每个可选参数都与之相关联.
这是我整理的一个简单的技巧,可能是一个合理的起点:
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()
Run Code Online (Sandbox Code Playgroud)
它正在发挥作用:
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'])
Run Code Online (Sandbox Code Playgroud)
这个问题有一些挑战。首先,您想要接受任意数量的位置参数—— 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)。