【问题标题】:Python: how can I ingest arguments from JSON file?Python:如何从 JSON 文件中提取参数?
【发布时间】:2016-02-26 21:54:15
【问题描述】:

我有一段 Python 代码可以提取命令行参数,例如:

import argparse
if __name__ == "__main__":                # myScript.py
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--int", help="Int with default", type=int, default=20)
    parser.add_argument("-swd", "--strwdef", help="string with default", type=str, default="DEFAULTSTRING")
    parser.add_argument("-snd", "--strnodef", help="string without default", type=str)
    parser.add_argument("-f", "--flag", help="binary flag", action='store_true')
    args = parser.parse_args()
    i = args.i
    swd = args.swd
    snd = args.snd
    f = args.flag

所以这适用于这样的命令:

python myScript.py -swd SomeString --int 35 -f

我想改为从 JSON 文件中读取这些参数。问题:

  1. python 2.7 中是否有内置功能来设置它,而不是编写我自己的 json.load() 解析结果的自定义代码来处理参数类型、默认值等?
  2. 如果有,上述示例的 JSON 文件的正确格式是什么,以及填充变量 iswd 等的方式?

谢谢!

【问题讨论】:

标签: python json python-2.7 argparse


【解决方案1】:

解析器中的args 是一个argparse.Namespace 对象,很容易变成字典

 vars(args)

-swd SomeString --int 35 -f 会产生类似namespace(swd='SomeString', int=35, f=True){'swd':'SomeString', 'int':35, 'f':True} 的内容。

等效的 JSON 将解码为类似的字典。

字典可以通过以下方式转换(返回)为命名空间:

In [2]: dd={'swd':'SomeString', 'int':35, 'f':True}
In [3]: dd
Out[3]: {'f': True, 'int': 35, 'swd': 'SomeString'}
In [4]: argparse.Namespace(**dd)
Out[4]: Namespace(f=True, int=35, swd='SomeString')

据我所知,没有一个包可以像推理一样将argparse 应用于字典(可能是由json.loads 创建的)。

最近有人问是否有一种方法可以基于namespace 重新创建sys.argv 字符串。你可以查一下。

我可以使用此代码重新创建 sys.argv 喜欢列表

In [22]: def foo(k,v):
    if len(k)==1:
        k =  '-'+k
    else:
        k = '--'+k
    if isinstance(v,bool):
        return (k,)
    else:
        return k,str(v)
   ....:     
In [23]: argv=[]
In [24]: for k,v in dd.items():
    argv.extend(foo(k,v))
   ....:     
In [25]: argv
Out[25]: ['-f', '--int', '35', '--swd', 'SomeString']

然后可以将其传递给您的解析器:

args = parser.parse_args(argv)

==========================

您可以做的另一件事是使用默认值创建一个字典,并从 JSON 字典更新它:

In [27]: defaultd=dict(int=20, strwdef='DEFAULTSTRING',snd=None,flag=False)
In [28]: defaultd
Out[28]: {'strwdef': 'DEFAULTSTRING', 'snd': None, 'int': 20, 'flag': False}
In [29]: defaultd.update(dd)
In [30]: defaultd
Out[30]: 
{'strwdef': 'DEFAULTSTRING',
 'f': True,
 'flag': False,
 'swd': 'SomeString',
 'snd': None,
 'int': 35}

我刚刚注意到一个问题。对于defaultd,我使用了长名称“flag”名称,但在 JSON dict 中我使用了短名称“f”。

我可以选择性地从 JSON dict 中复制,例如:

In [32]: for k in defaultd:
   ....:     if k in dd:
   ....:         defaultd[k]=dd[k]
   ....:         
In [33]: defaultd
Out[33]: {'strwdef': 'DEFAULTSTRING', 'snd': None, 'int': 35, 'flag': False}

处理“坏”值或别名会更复杂。

【讨论】:

  • As far as I know there isn't a package that would apply argparse like reasoning to a dictionary - 这就是模式库的用途。
【解决方案2】:

所以下面是您可以做到这一点的一种方法。我不确定它有多安全。 JSON 键应与您需要将其解析成的变量相同。

j = json.loads(...)
print j  # {'swd': 'someString', 'i': 35}
locals().update(j)
print swd, i  # someString 35

docs for locals 建议不要修改,因此使用此内容需要您自担风险。

我很快想到的一个更安全的解决方法是在将 argparsing 后的结果存储到字典中。从 JSON 导入它们时,只需单独更新该字典即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2022-01-19
    • 2016-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多