argparse.add_argument()中的type=dict

44 投票
14 回答
36567 浏览
提问于 2025-04-17 03:31

我想用标准库里的 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'}

撰写回答