Python argparse 字典 arg
Posted
技术标签:
【中文标题】Python argparse 字典 arg【英文标题】:Python argparse dict arg 【发布时间】:2015-07-11 05:52:31 【问题描述】:我想从命令行接收dict(str -> str)
参数。 argparse.ArgumentParser
提供吗?还是其他图书馆?
对于命令行:
program.py --dict d --key key1 --value val1 --key key2 --value val2
我期待以下字典:
d = "key1": "val1", "key2": "val2"
【问题讨论】:
你是在做参数解析还是什么?将其收集到 dict 似乎并没有什么意义。 @skyline75489。是的。我解析 d 参数。为什么列表可以是参数,而字典不能.. 参数可能非常复杂。它可以是可选的或必需的、位置的或非位置的、需要值或不需要值。我想添加dict
支持会让事情变得更加复杂。
不如program.py --opt1 k1=v1,k2=v2,k3=v3
好吗?
另一种选择是将值作为(引用的)JSON 字符串输入。
【参考方案1】:
这是另一个使用自定义操作的解决方案,如果您想以逗号分隔一起指定字典键对 --
import argparse
import sys
parser = argparse.ArgumentParser(description='parse key pairs into a dictionary')
class StoreDictKeyPair(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
my_dict =
for kv in values.split(","):
k,v = kv.split("=")
my_dict[k] = v
setattr(namespace, self.dest, my_dict)
parser.add_argument("--key_pairs", dest="my_dict", action=StoreDictKeyPair, metavar="KEY1=VAL1,KEY2=VAL2...")
args = parser.parse_args(sys.argv[1:])
print args
跑步:
python parse_kv.py --key_pairs 1=2,a=bbb,c=4 --key_pairs test=7,foo=bar
输出:
Namespace(my_dict='1': '2', 'a': 'bbb', 'c': '4', 'test': '7', 'foo': 'bar')
如果你想在字符串中使用 nargs 而不是逗号分隔的值:
class StoreDictKeyPair(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
self._nargs = nargs
super(StoreDictKeyPair, self).__init__(option_strings, dest, nargs=nargs, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
my_dict =
print "values: ".format(values)
for kv in values:
k,v = kv.split("=")
my_dict[k] = v
setattr(namespace, self.dest, my_dict)
parser.add_argument("--key_pairs", dest="my_dict", action=StoreDictKeyPair, nargs="+", metavar="KEY=VAL")
args = parser.parse_args(sys.argv[1:])
print args
跑步
python arg_test4.py --key_pairs 1=2 a=bbb c=4 test=7 foo=bar
输出:
values: ['1=2', 'a=bbb', 'c=4', 'test=7', 'foo=bar']
Namespace(my_dict='1': '2', 'a': 'bbb', 'c': '4', 'test': '7', 'foo': 'bar')
【讨论】:
这绝对是最好的答案 被低估的答案。唉,我已经给了我所有的爱。 很好的答案(已经赞成),但这不会将布尔字符串解析为布尔值或作为字符串传递的其他数据类型(列表、字典)。需要评估价值。请注意!【参考方案2】:我会使用这样的东西:
p = argparse.ArgumentParser()
p.add_argument("--keyvalue", action='append',
type=lambda kv: kv.split("="), dest='keyvalues')
args = p.parse_args("--keyvalue foo=6 --keyvalue bar=baz".split())
d = dict(args.keyvalues)
您可以创建一个自定义操作,将已解析的键值对直接“附加”到字典中,而不是简单地累积(key, value)
元组的列表。 (我看到的是 skyline75489 所做的;我的答案不同之处在于使用带有自定义类型的单个 --keyvalue
选项,而不是单独的 --key
和 --value
选项来指定对。)
【讨论】:
谢谢。你的答案是最好的。 我建议使用kv.split("=", 1)
来允许=
在值中并确保您最多有2 个元素。
还有:if any(len(kv) < 2 for kv in args.keyvalues): raise ValueError('Values must be given in the form "KEY=VALUE"')
【参考方案3】:
只是另一种简单的方法:
parser = argparse.ArgumentParser()
parser.add_argument('--key1')
parser.add_argument('--key2')
args = parser.parse_args()
my_dict = args.__dict__
【讨论】:
不,我不想将 agruments 转换为字典。很容易做到:arguments = vars(parser.parse_args())
。请用示例重新阅读问题
访问您无法控制的类的__dict__
属性通常不是一个好习惯,因为它可能包含您不期望的元数据。【参考方案4】:
Python 以数组argv
的形式接收参数。您可以使用它在程序本身中创建字典。
import sys
my_dict =
for arg in sys.argv[1:]:
key, val=arg.split(':')[0], arg.split(':')[1]
my_dict[key]=val
print my_dict
对于命令行:
python program.py key1:val1 key2:val2 key3:val3
输出:
my_dict = 'key3': 'val3', 'key2': 'val2', 'key1': 'val1'
注意:args 将是字符串,因此您必须将它们转换为存储数值。
希望对你有帮助。
【讨论】:
我认为您的解决方案还可以,但有点脏。 1. 键和值不能包含':' 2. 多个参数的顺序太难控制 我给出的不是唯一的解决方案,关键是你有一个参数列表 - ['key1', 'val1', 'key2', 'val2', 'key3', 'val3 '],因此可以使用任何逻辑获得 dict,例如:每个偶数元素(例如 pos 'i')是键,它的值将在 pos (i+1),所以只需以步长运行循环2 并存储字典。【参考方案5】:Python 单行 argparse 字典参数argparse_dictionary.py
# $ python argparse_dictionary.py --arg_dict=1=11,2=22;3=33 --arg_dict=a=,b,c=cc,=dd,=ee=,
# Namespace(arg_dict='1': '11', '2': '22', '3': '33', 'a': '', 'c': 'cc', '': 'dd')
import argparse
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument(
'--arg_dict',
action=type(
'', (argparse.Action, ),
dict(__call__=lambda self, parser, namespace, values, option_string: getattr(
namespace, self.dest).update(
dict([
v.split('=') for v in values.replace(';', ',').split(',')
if len(v.split('=')) == 2
])))),
default=,
metavar='KEY1=VAL1,KEY2=VAL2;KEY3=VAL3...',
)
print(arg_parser.parse_args())
【讨论】:
好点,但我很抱歉 - 这是不可读的代码。请使用 pep8。【参考方案6】:使用变量
d = vars(parser.parse_args())
【讨论】:
感谢您的贡献。但是您的代码并不能解决问题。它只是将所有传递的参数转换为字典,但代码也应该使用未知的动态键。【参考方案7】:解析输入的直接方式,例如:
program.py --dict d --key key1 --value val1 --key key2 --value val2
是:
parser=argparse.ArgumentParser()
parser.add_argument('--dict')
parser.add_argument('--key', action='append')
parser.add_argument('--value', action='append')
args = parser.parse_args()
应该产生(如果我的心理解析器是正确的)
args = Namespace(dict='d', key=['key1','key2'], value=['value1','value2'])
您应该可以使用以下方法构建字典:
adict = k:v for k, v in zip(args.key, args.value)
使用args.dict
将其分配给具有该名称的变量需要一些非python 技巧。最好的办法是在另一个字典中使用此名称创建一个元素。
another_dict = args.dict: adict
此解决方案不会执行太多错误检查。例如,它不能确保有相同数量的键和值。它也不会让您创建多个字典(即重复 --dict
参数)。它不需要任何特殊订单。 --dict
可能出现在 --key key1
对之后。几个--value
参数可以放在一起。
将key=value
与chepner
绑定在一起确实可以解决许多这些问题。
【讨论】:
【参考方案8】:如果您只是想将 argparse 输入转换为字典,那么 Python 3.6 中有一个简单的解决方案。一个例子如下:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', help='the path to the input file')
parser.add_argument('-o', '--output', help='the path to the output file')
args = parser.parse_args()
arguments = dict(args._get_kwargs())
for k, v in arguments.items():
print(k, v)
给定命令行输入,例如python3 script_name.py --input 'input.txt' --output 'output.txt'
,代码将输出到终端:
input input.txt
output output.txt
【讨论】:
不,我不想将 agruments 转换为字典。无需使用隐藏字段即可轻松完成:arguments = vars(parser.parse_args())
。请用示例重新阅读问题。
arguments = vars(parser.parse_args())
在这种情况下,这通常是您想要的。【参考方案9】:
目前的库如argparse、docopt和click,都不支持使用dict
args。我能想到的最佳解决方案是自定义argparse.Action
来支持它自己:
import argparse
class MyAction(argparse.Action):
def __init__(self, option_strings, dest, nargs=None, **kwargs):
super(MyAction, self).__init__(option_strings, dest, nargs, **kwargs)
def __call__(self, parser, namespace, values, option_string=None):
print '%r %r %r' % (namespace, values, option_string)
value_dict =
values.reverse()
while len(values) > 0:
v = eval(values.pop()).lstrip('--') # This is like crazy hack, I know.
k = eval(values.pop())
value_dict[k] = v
setattr(namespace, self.dest, value_dict)
parser = argparse.ArgumentParser()
parser.add_argument('-d', action=MyAction, nargs='*')
args = parser.parse_args('-d "--key" "key1" "--value" "val1" "--key" "key2" "--value" "val2"'.split())
print(args)
【讨论】:
以上是关于Python argparse 字典 arg的主要内容,如果未能解决你的问题,请参考以下文章
使用 argparse 和 python 接受字典作为参数 [重复]
将 Python argparse.Namespace() 视为字典的正确方法是啥?
编程54--python学习28Namespace与dict的相互转换,保存Namespace,以字典形式传入argparse的参数