使用 Argparse 和 Json 共同处理

2024-06-28 19:25:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我是Python初学者。

我想知道Argparse和JSON是否可以一起使用。 比如,我有变量p,q,r

我可以把它们作为-

parser.add_argument('-p','--param1',help='x variable', required=True)
parser.add_argument('-q','--param2',help='y variable', required=True)
parser.add_argument('-r','--param3',help='z variable', required=True)

现在假设我想从JSON文件中读取相同的变量,有可能吗? 所以我可以从命令行或JSON文件中输入值。

JSON输入文件-

{
    "testOwner": "my name",
    "tests": [
        "test1",
        "test2",
        "test3"
    ],

    "testParameters": {
        "test1": {
            "param1": "0",
            "param2": "20",
            "param3" : "True"
        },

        "test2": {
            "param1": "cc"
        }
    }   
}

Tags: 文件addjsontrueparserrequiredhelpargument
2条回答

来自parse_argsargs命名空间可以转换为具有以下内容的字典:

argparse_dict = vars(args)

JSON值也在字典中,比如json_dict。您可以将选定的值从一个字典复制到另一个字典,或执行整个刻度更新:

argparse_dict.update(json_dict)

这样,json_dict值就会覆盖argparse值。

如果要同时保留这两个值,则需要使用不同的参数(键)名称,或者值必须是列表,可以附加或扩展列表。这需要更多的工作,首先在argparse中使用正确的nargs值。


修改后的parser生成一个测试输入:

In [292]: args=parser.parse_args('-p one -q two -r three'.split())
In [293]: args
Out[293]: Namespace(param1='one', param2='two', param3='three')
In [295]: args_dict = vars(args)    
In [296]: args_dict
Out[296]: {'param1': 'one', 'param2': 'two', 'param3': 'three'}

解析时的JSON字符串(json.loads?)生成如下词典:

In [317]: json_dict
Out[317]: 
{'testOwner': 'my name',
 'testParameters': {'test1': {'param1': '0', 'param2': '20', 'param3': 'True'},
  'test2': {'param1': 'cc'}},
 'tests': ['test1', 'test2', 'test3']}

我是通过将您的显示粘贴到我的Ipython会话中来实现这一点的,但是我认为JSON加载程序也会产生同样的结果

argparse值可以添加为:

In [318]: json_dict['testParameters']['test3']=args_dict
In [319]: json_dict
Out[319]: 
{'testOwner': 'my name',
 'testParameters': {'test1': {'param1': '0', 'param2': '20', 'param3': 'True'},
  'test2': {'param1': 'cc'},
  'test3': {'param1': 'one', 'param2': 'two', 'param3': 'three'}},
 'tests': ['test1', 'test2', 'test3']}

在这里,我将它添加为第三个test集,从tests列表中获取一个名称(根据conincidence)。json_dict['testParameters']['test2']=args_dict将替换test2的值。

将args值添加到“test2”的未定义值的一种方法是:

In [320]: args_dict1=args_dict.copy()    
In [322]: args_dict1.update(json_dict['testParameters']['test2'])
In [324]: json_dict['testParameters']['test2']=args_dict1
In [325]: json_dict
Out[325]: 
{'testOwner': 'my name',
 'testParameters': {'test1': {'param1': '0', 'param2': '20', 'param3': 'True'},
  'test2': {'param1': 'cc', 'param2': 'two', 'param3': 'three'},
  'test3': {'param1': 'one', 'param2': 'two', 'param3': 'three'}},
 'tests': ['test1', 'test2', 'test3']}

我使用这个版本的update优先考虑JSON字典中的'cc'值。

假设您的JSON文件包含以下格式的dict:

d = {"name": ["-x", "--xvar"], "help": "Help message", "required": True}

创建解析器之后,您可以像这样“解包”dict:

parser = argparse.ArgumentParser()
parser.add_argument(*(d.pop("name")), **d) 
# Put the 'name' as name/flag and then unpack the rest of
# the dict as the rest of the arguments
parser.parse_args("--xvar 12".split())
>>> Namespace(xvar='12')

但是,这会迫使您维护dict键以适合方法add_arguments的参数名。您也没有一个简单/直接的方法来使用更高级的行为,比如使用actiontypechoices参数。

此外,还必须更改dict的格式,以包含要使用的各种参数。一种解决方案是将名称/标志作为元组中dict的键,而参数将是dict:

d = {("-x", "--xvar"): {"help": "Help message for x", "required": True}, 
     ("-y", "--yvar"): {"help": "Help message for y", "required": True}}
for names, args in d.iteritems():
    parser.add_argument(*names, **args) # Use a similar unpacking 'magic' as the first example
parser.parse_args("-x 12 --yvar 42".split())
>>> Namespace(xvar='12', yvar='42')

编辑 考虑到来自OP的注释,他似乎希望解析取自JSON文件的值。

d = {"-x": "12", "-y": "42"}
args = []
for item in d.items():
    args.extend(item)
parser.parse_args(args)
>>> Namespace(xvar='12', yvar='42')

编辑2

看看argparse文档this paragraph可能有点相关。

相关问题 更多 >