我想从命令行接收一个dict(str -> str)
参数。 argparse.ArgumentParser
提供了吗?还是有其他的库可以使用?
针对命令行:
program.py --dict d --key key1 --value val1 --key key2 --value val2
我期望得到以下的字典:
d = {"key1": "val1", "key2": "val2"}
我想从命令行接收一个dict(str -> str)
参数。 argparse.ArgumentParser
提供了吗?还是有其他的库可以使用?
针对命令行:
program.py --dict d --key key1 --value val1 --key key2 --value val2
我期望得到以下的字典:
d = {"key1": "val1", "key2": "val2"}
如果您想要一起使用逗号分隔的字典键值对,请使用自定义操作的另一种解决方案--
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'})
my_dict[k] = ast.literal_eval(v)
来实现类型转换。 - eqzx__call__
方法中,我不得不使用my_dict = getattr(namespace, self.dest, {})
来使其在我切换到使用子解析器后正常工作,非常感谢,这太棒了。 - Daniel Griffin我会使用类似这样的东西:
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)
来允许值中包含=
,并确保最多只有两个元素。 - Ryan Fox如果args.keyvalues中有任何一个kv的长度小于2,则引发ValueError('值必须以"KEY=VALUE"的形式给出')
。 - Ryan Fox另一种简单的方法:
parser = argparse.ArgumentParser()
parser.add_argument('--key1')
parser.add_argument('--key2')
args = parser.parse_args()
my_dict = args.__dict__
arguments = vars(parser.parse_args())
。请结合示例重新阅读问题。 - orion_tvv__dict__
属性,因为其中可能包含意料之外的元数据。 - jtschoonhoven使用 vars
d = vars(parser.parse_args())
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'}
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())
解析输入的一种直接方法,例如:
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
参数可以放在一起。
像chepner
所做的将key=value
绑定在一起可以解决其中许多问题。
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
arguments = vars(parser.parse_args())
。请重新阅读带有示例的问题。 - orion_tvvarguments = vars(parser.parse_args())
在这种情况下通常是您想要的。 - kontur至于当前的库,例如argparse、docopt和click,它们都不支持使用dict
作为参数。我能想到的最好的解决方案是自定义一个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)
dict
支持会让事情变得更加复杂。 - ljk321program.py --opt1 k1=v1,k2=v2,k3=v3
不是更好吗? - shx2