我有一个需要配置文件的Python测试脚本.配置文件应采用JSON格式.
但是我的测试脚本的一些用户不喜欢JSON格式,因为它不可读.
所以我更改了我的测试脚本,以便它需要YAML格式的配置文件,然后将YAML文件转换为JSON文件.
我更喜欢加载配置文件以处理JSON和YAML的函数.如果配置文件是JSON或YAML,yaml或json模块中是否有一个方法可以给我一个布尔响应?
我现在的解决方法是使用两个try/except子句:
import os
import json
import yaml
# This is the configuration file - my script gets it from argparser but in
# this example, let's just say it is some file that I don't know what the format
# is
config_file = "some_config_file"
in_fh = open(config_file, "r")
config_dict = dict()
valid_json = True
valid_yaml = True
try:
config_dict = json.load(in_fh)
except:
print "Error trying to load the config file in JSON format"
valid_json = False
try:
config_dict = yaml.load(in_fh)
except:
print "Error trying to load the config file in YAML format"
valid_yaml = False
in_fh.close()
if not valid_yaml and not valid_json:
print "The config file is neither JSON or YAML"
sys.exit(1)
Run Code Online (Sandbox Code Playgroud)
现在,我在Internet上找到了一个名为isityaml的Python模块,可用于测试YAML.但我不想安装另一个包,因为我必须在几个测试主机上安装它.
json和yaml模块是否有一个方法可以返回一个布尔值来测试它们各自的格式?
config_file = "sample_config_file"
# I would like some method like this
if json.is_json(in_fh):
config_dict = json.load(in_fh)
Run Code Online (Sandbox Code Playgroud)
从你的
import yaml
Run Code Online (Sandbox Code Playgroud)
我的结论是你使用旧的PyYAML.该软件包仅支持YAML 1.1(从2005年开始),并且指定的格式不是JSON的完整超集.使用YAML 1.2(2009年发布),YAML格式成为JSON的超集.
包ruamel.yaml(免责声明:我是该包的作者)支持YAML 1.2.因此,通过替换PyYAML ruamel.yaml(而不是添加包),您可以这样做:
import os
from ruamel import yaml
config_file = "some_config_file"
with open(config_file, "r") as in_fh:
config_dict = yaml.safe_load(in_fh)
Run Code Online (Sandbox Code Playgroud)
并加载文件config_dict,而不是关心输入是YAML还是JSON,也不需要对任何一种格式进行测试.
请注意,我用safe_load()的使用load()上,你有没有100%的控制权YAML文件(你没有)是不安全的.(ruamel.yaml会警告你,PyYAML没有).
从查看json和yaml模块的文档来看,它们似乎没有提供任何合适的模块。然而,一个常见的 Python 习惯用法是EAFP(“请求宽恕比请求许可更容易”);换句话说,继续尝试执行操作,并在出现异常时进行处理。
def load_config(config_file):
with open(config_file, "r") as in_fh:
# Read the file into memory as a string so that we can try
# parsing it twice without seeking back to the beginning and
# re-reading.
config = in_fh.read()
config_dict = dict()
valid_json = True
valid_yaml = True
try:
config_dict = json.loads(config)
except:
print "Error trying to load the config file in JSON format"
valid_json = False
try:
config_dict = yaml.safe_load(config)
except:
print "Error trying to load the config file in YAML format"
valid_yaml = False
Run Code Online (Sandbox Code Playgroud)
如果您愿意,您可以自己制作is_json或运行。is_yaml这将涉及处理配置两次,但这可能适合您的目的。
def try_as(loader, s, on_error):
try:
loader(s)
return True
except on_error:
return False
def is_json(s):
return try_as(json.loads, s, ValueError)
def is_yaml(s):
return try_as(yaml.safe_load, s, yaml.scanner.ScannerError)
Run Code Online (Sandbox Code Playgroud)
最后,正如 @user2357112 所提到的,“每个 JSON 文件也是一个有效的 YAML 文件”(从 YAML 1.2 开始),因此您应该能够无条件地将所有内容处理为 YAML(假设您有一个与 YAML 1.2 兼容的解析器;Python 的默认解析器)yaml模块不是)。