一起使用 Argparse 和 Json
Using Argparse and Json together
我是 Python 的初学者。
我想知道 Argparse 和 JSON 是否可以一起使用。
说,我有变量 p,q,r
我可以将它们添加到 argparse 作为 -
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"
}
}
}
鉴于您的 JSON 文件包含以下形式的字典:
d = {"name": ["-x", "--xvar"], "help": "Help message", "required": True}
创建解析器后,您可以 "unpack" 字典如下:
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')
然而,这迫使您维护字典键以适应方法的参数名称 add_arguments
。您也没有 simple/straight 使用更高级行为的前向方式,例如使用 action
、type
、choices
参数。
此外,您还必须更改字典的形式以包含您要使用的各种参数。一种解决方案是将 name/flag 作为元组中字典的键,参数将是一个字典:
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 可能有点相关。
来自 parse_args
的 args
命名空间可以转换为字典:
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']}
我在这里将它添加为第 3 个 test
集,(巧合地)从 tests
列表中取了一个名字。 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' 值。
事实证明,以下注意事项非常简单
- 安装程序使用命令行中的值覆盖配置文件中的值
- 如果没有在命令行或设置文件中设置选项,它只使用默认值
- 它不检查配置文件中的设置是否有效
import argparse
import json
parser = argparse.ArgumentParser()
parser.add_argument('--save_json',
help='Save settings to file in json format. Ignored in json file')
parser.add_argument('--load_json',
help='Load settings from file in json format. Command line options override values in file.')
args = parser.parse_args()
if args.load_json:
with open(args.load_json, 'rt') as f:
t_args = argparse.Namespace()
t_args.__dict__.update(json.load(f))
args = parser.parse_args(namespace=t_args)
# Optional: support for saving settings into a json file
if args.save_json:
with open(args.save_json, 'wt') as f:
json.dump(vars(args), f, indent=4)
我是 Python 的初学者。
我想知道 Argparse 和 JSON 是否可以一起使用。
说,我有变量 p,q,r
我可以将它们添加到 argparse 作为 -
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"
}
}
}
鉴于您的 JSON 文件包含以下形式的字典:
d = {"name": ["-x", "--xvar"], "help": "Help message", "required": True}
创建解析器后,您可以 "unpack" 字典如下:
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')
然而,这迫使您维护字典键以适应方法的参数名称 add_arguments
。您也没有 simple/straight 使用更高级行为的前向方式,例如使用 action
、type
、choices
参数。
此外,您还必须更改字典的形式以包含您要使用的各种参数。一种解决方案是将 name/flag 作为元组中字典的键,参数将是一个字典:
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 可能有点相关。
来自 parse_args
的 args
命名空间可以转换为字典:
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']}
我在这里将它添加为第 3 个 test
集,(巧合地)从 tests
列表中取了一个名字。 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' 值。
事实证明,以下注意事项非常简单
- 安装程序使用命令行中的值覆盖配置文件中的值
- 如果没有在命令行或设置文件中设置选项,它只使用默认值
- 它不检查配置文件中的设置是否有效
import argparse
import json
parser = argparse.ArgumentParser()
parser.add_argument('--save_json',
help='Save settings to file in json format. Ignored in json file')
parser.add_argument('--load_json',
help='Load settings from file in json format. Command line options override values in file.')
args = parser.parse_args()
if args.load_json:
with open(args.load_json, 'rt') as f:
t_args = argparse.Namespace()
t_args.__dict__.update(json.load(f))
args = parser.parse_args(namespace=t_args)
# Optional: support for saving settings into a json file
if args.save_json:
with open(args.save_json, 'wt') as f:
json.dump(vars(args), f, indent=4)