我有一个需要配置文件的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)
现在,我在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)
答案 0 :(得分:5)
来自你的
import yaml
我的结论是你使用旧的PyYAML。该软件包仅支持YAML 1.1(从2005年开始),并且指定的格式不是JSON的完整超集。使用YAML 1.2(2009年发布),YAML格式成为JSON的超集。
包ruamel.yaml
(免责声明:我是该包的作者)支持YAML 1.2。因此,通过ruamel.yaml
替换PyYAML(而不是添加包),您可以这样做:
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)
并将文件加载到config_dict
,不关心输入是YAML还是JSON,也不需要对这两种格式进行测试。
请注意,我使用safe_load()
在您无法100%控制的YAML文件上使用load()
(并且您没有)是不安全的。 (ruamel.yaml会警告你,PyYAML没有)。
答案 1 :(得分:0)
通过查看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
如果您愿意,可以创建自己的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)
最后,正如@ user2357112所提到的,"every JSON file is also a valid YAML file"(从YAML 1.2开始),所以你应该能够无条件地处理所有内容为YAML(假设你有一个兼容YAML 1.2的解析器; Python的默认值{{1 }}模块不是。)
答案 2 :(得分:0)
几年后,我遇到了同样的麻烦。我完全同意EAFP,但是如果配置文件为JSON格式或YAML,我仍然在尝试寻找最佳检测方法。 在代码中,我有一些方法可以通知用户在中他确实在json文件中发布以及在YAML中的哪个位置发布。 try / except没有按照我真正想要的处理,当我看到这些嵌套的块时,我的眼睛在流血。
这并不完美,仍然存在一些小问题,但是对我来说,基本概念符合我的需求。我会说“足够好”。
我的解决方案是:在配置文件中找到所有可能的独立逗号。如果配置文件包含独立的逗号(json中的分隔符),则我们有json文件,如果找不到任何逗号,则为yaml。 在我的yaml文件中,仅在注释(在“”之间)和列表(在[]之间)中使用逗号。 也许有人会觉得有用。
IWebElement channel = driver.FindElement(By.XPath("//*[@id=\"text\"]/a[contains(@href, '/channel/UCV1Nlv5cOSB--hEjRVo4mUA')]"));