argparse.add_argument()中的type=dict
我想用标准库里的 argparse
模块来解析我程序的命令行参数,并让程序接受一个可选的参数 -i
(或者 --image
),这个参数是一个字典。
我试着这样配置解析器:
parser.add_argument('-i','--image', type=dict, help='Generate an image map from the input file (syntax: {\'name\': <name>, \'voids\': \'#08080808\', \'0\': \'#00ff00ff\', \'100%%\': \'#ff00ff00\'}).')
但是当我尝试运行这个脚本时,出现了一个错误:
$ ./script.py -i {'name': 'img.png','voids': '#00ff00ff','0': '#ff00ff00','100%': '#f80654ff'}
script.py: error: argument -i/--image: invalid dict value: '{name:'
尽管类似的语法在解释器里运行得很好:
>>> a={'name': 'img.png','voids': '#00ff00ff','0': '#ff00ff00','100%': '#f80654ff'}
我应该怎么做才能 a) 写出正确的命令行,b) 设置好 argparse
的逻辑呢?
14 个回答
13
使用简单的lambda解析非常灵活:
parser.add_argument(
'--fieldMap',
type=lambda x: {k:int(v) for k,v in (i.split(':') for i in x.split(','))},
help='comma-separated field:position pairs, e.g. Date:0,Amount:2,Payee:5,Memo:9'
)
18
为了完整性,和json.loads类似,你可以使用yaml.load(这个在PyYAML库中可以找到)。它比json的一个好处是,你在命令行中不需要给每个键和值加引号,除非你想把整数强制转换成字符串,或者想解决yaml转换时的一些问题。不过,显然整个字符串还是需要加引号,因为里面有空格!
>>> import argparse
>>> import yaml
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-fna', '--filename-arguments', type=yaml.load)
>>> data = "{location: warehouse A, site: Gloucester Business Village}"
>>> ans = parser.parse_args(['-fna', data])
>>> print ans.filename_arguments['site']
Gloucester Business Village
虽然在提问中,很多键和值确实需要加引号或者重新表述,以免yaml出错。使用以下数据似乎效果很好,如果你需要数字而不是字符串的话:
>>> parser.add_argument('-i', '--image', type=yaml.load)
>>> data = "{name: img.png, voids: 0x00ff00ff, '0%': 0xff00ff00, '100%': 0xf80654ff}"
>>> ans = parser.parse_args(['-i', data])
>>> print ans.image
{'100%': 4161164543L, 'voids': 16711935, 'name': 'img.png', '0%': 4278255360L}
71
提到这个问题:json.loads
在这里也能用。看起来并没有什么不妥。
import json
import argparse
test = '{"name": "img.png","voids": "#00ff00ff","0": "#ff00ff00","100%": "#f80654ff"}'
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', type=json.loads)
args = parser.parse_args(['-i', test])
print(args.input)
返回结果:
{u'0': u'#ff00ff00', u'100%': u'#f80654ff', u'voids': u'#00ff00ff', u'name': u'img.png'}