我有一个通过命令行获取命名参数的脚本。其中一个参数可以多次提供。例如,我想运行一个脚本:
./script.py --add-net=user1:10.0.0.0/24 --add-net=user2:10.0.1.0/24 --add-net=user3:10.0.2.0/24
现在我想要一个argparse操作,它将解析每个参数并将结果存储在dict中,如下所示:
^{pr2}$此外,如果没有提供值,则应该提供一个默认值。像
./script.py
应该有dict像:
{'user': '192.168.0.0/24'}
我相信我必须为argparse构建一个自定义操作。我想到的是:
class ParseIPNets(argparse.Action):
"""docstring for ParseIPNets"""
def __init__(self, option_strings, dest, nargs=None, **kwargs):
super(ParseIPNets, self).__init__(option_strings, dest, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
for value in values:
location, subnet = values.split(':')
namespace.user_nets[location] = subnet
parser = argparse.ArgumentParser(description='foo')
parser.add_argument('--add-net',
nargs='*',
action=ParseIPNets,
dest='user_nets',
help='Nets subnets for users. Can be used multiple times',
default={"user1": "198.51.100.0/24"})
args = parser.parse_args()
当我需要使用默认值时,这很好:
test.py
Namespace(user_nets={'user1': '198.51.100.0/24'})
但是,当我添加参数时,它们被附加到默认值中。我的期望是将它们添加到一个空的dict中:
test.py --add-net=a:10.0.0.0/24 --add-net=b:10.1.0.0/24
Namespace(user_nets={'a': '10.0.0.0/24', 'b': '10.1.0.0/24', 'user1': '198.51.100.0/24'})
怎样才能得到我想要的东西?在
使用可变的默认参数(在您的例子中是dict)通常不是一个好主意,请参见here了解解释:
我解决这个问题的第一种方法是使用
action='append'
,并在解析后将结果列表转换为字典。代码量也差不多。在“append”在默认值上也有同样的问题。如果
default=['defaultstring']
,则列表也将以该值开头。我将通过使用默认默认值([]见下文)来解决这个问题,并在后期处理中添加默认值(如果列表仍然为空或无)。在关于违约的说明。在
parse_args
的开头,所有操作默认值都被添加到名称空间中(除非名称空间作为parse_args
的参数给定)。然后解析命令行,每个操作对命名空间执行自己的操作。最后,使用type
函数转换任何剩余的字符串默认值。在在您的例子中,
namespace.user_nets[location] = subnet
找到user_nets
属性,并添加新条目。默认情况下,该属性被初始化为字典,因此默认值出现在最终字典中。事实上,如果将默认值保留为None
或某个字符串,则代码将无法工作。在_AppendAction
类的call
可能具有指导意义:_ensure_value
是在argparse
中定义的函数。_copy
是它导入的标准copy
模块。在_ensure_value
的作用类似于字典get(key, value, default)
,但与namespace
对象一起使用除外。在本例中,如果self.dest
没有值(或者值是None
),则返回一个空列表。因此,它确保append以一个列表开始。在_copy.copy
确保它向副本追加值。这样,parse_args
将不会修改default
。它避免了@miles82
所指出的问题。在所以'append action'在
call
本身中定义了初始空列表。并使用copy
来避免修改任何其他默认值。在你想要}?在
^{pr2}$values
而不是{我倾向于把这个转换放在一个类型函数中,例如
这也是进行错误检查的好地方。在
在操作或解析后,可以使用
update
将它们添加到现有的词典中。在很明显,
argparse
在内部将默认值作为结果对象的初始值,因此不应在add_argument
调用中直接设置默认值,而是进行一些额外的处理:或者,如果希望获得更好的用户体验,可以使用Python处理可变默认参数的方式:
^{pr2}$这样,如果选项存在,可选的默认值将被清除。在
但是注意:这只在第一次调用脚本时有效。这里可以接受,因为
parser.parse_args()
在脚本中只应调用一次。在附带说明:我删除了
nargs='*'
,因为如果你这样称呼它,我发现它比有用的更危险,而且还删除了values
上始终使用values
的错误循环:nargs='*'
对以下语法有意义:代码应该是:
相关问题 更多 >
编程相关推荐