有没有办法确定文件是YAML还是JSON格式?

SQA*_*777 4 python json yaml

我有一个需要配置文件的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)

Ant*_*hon 5

从你的

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没有).


Jos*_*ley 4

从查看jsonyaml模块的文档来看,它们似乎没有提供任何合适的模块。然而,一个常见的 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模块不是)。