繁体   English   中英

在 python 中验证 yaml 文档

[英]Validating a yaml document in python

XML 的好处之一是能够根据 XSD 验证文档。 YAML 没有此功能,那么如何验证我打开的 YAML 文档是否符合我的应用程序所需的格式?

鉴于 JSON 和 YAML 是非常相似的野兽,您可以使用JSON-Schema来验证相当大的 YAML 子集。 这是一个代码片段(您需要安装PyYAMLjsonschema ):

from jsonschema import validate
import yaml

schema = """
type: object
properties:
  testing:
    type: array
    items:
      enum:
        - this
        - is
        - a
        - test
"""

good_instance = """
testing: ['this', 'is', 'a', 'test']
"""

validate(yaml.load(good_instance), yaml.load(schema)) # passes

# Now let's try a bad instance...

bad_instance = """
testing: ['this', 'is', 'a', 'bad', 'test']
"""

validate(yaml.load(bad_instance), yaml.load(schema))

# Fails with:
# ValidationError: 'bad' is not one of ['this', 'is', 'a', 'test']
#
# Failed validating 'enum' in schema['properties']['testing']['items']:
#     {'enum': ['this', 'is', 'a', 'test']}
#
# On instance['testing'][3]:
#     'bad'

这样做的一个问题是,如果您的架构跨越多个文件并且您使用"$ref"来引用其他文件,那么我认为这些其他文件将需要是 JSON。 但可能有办法解决这个问题。 在我自己的项目中,我正在尝试使用 JSON 文件指定模式,而实例是 YAML。

我发现Cerberus非常可靠,文档丰富且易于使用。

这是一个基本的实现示例:

my_yaml.yaml :

name: 'my_name'
date: 2017-10-01
metrics:
    percentage:
    value: 87
    trend: stable

schema.py定义验证模式:

{
    'name': {
        'required': True,
        'type': 'string'
    },
    'date': {
        'required': True,
        'type': 'date'
    },
    'metrics': {
        'required': True,
        'type': 'dict',
        'schema': {
            'percentage': {
                'required': True,
                'type': 'dict',
                'schema': {
                    'value': {
                        'required': True,
                        'type': 'number',
                        'min': 0,
                        'max': 100
                    },
                    'trend': {
                        'type': 'string',
                        'nullable': True,
                        'regex': '^(?i)(down|equal|up)$'
                    }
                }
            }
        }
    }
}

使用PyYaml加载yaml文档:

import yaml
def load_doc():
    with open('./my_yaml.yaml', 'r') as stream:
        try:
            return yaml.load(stream)
        except yaml.YAMLError as exception:
            raise exception

## Now, validating the yaml file is straightforward:
from cerberus import Validator
schema = eval(open('./schema.py', 'r').read())
    v = Validator(schema)
    doc = load_doc()
    print(v.validate(doc, schema))
    print(v.errors)

请记住,Cerberus 是一个不可知的数据验证工具,这意味着它可以支持 YAML 以外的格式,例如 JSON、XML 等。

试试Rx ,它有一个 Python 实现。 它适用于 JSON 和 YAML。

从 Rx 站点:

“在向 Web 服务添加 API 时,您必须选择如何对通过线路发送的数据进行编码。为此,XML 是一种常见选择,但它很快就会变得晦涩难懂。许多 Web 服务作者希望避免考虑 XML,而是选择提供一些与现代编程语言中常见数据结构相对应的简单数据类型的格式,即 JSON 和 YAML。

不幸的是,虽然这些格式可以很容易地传递复杂的数据结构,但它们缺乏验证系统。 XML 有 XML Schemas 和 RELAX NG,但这些标准很复杂,有时令人困惑。 它们对于 JSON 提供的那种数据结构不是很容易移植,如果您想避免将 XML 作为数据编码,编写更多的 XML 来验证第一个 XML 可能更不吸引人。

Rx 旨在提供一个数据验证系统,该系统与 JSON 风格的数据结构相匹配,并且与 JSON 本身一样易于使用。”

是的 - 支持验证对于许多重要用例至关重要。 参见YAML 和模式验证的重要性« Stuart Gunter

如前所述,有Rx可用于各种语言,还有Kwalify 可用于 Ruby 和 Java。

另请参阅 PyYAML 讨论: YAMLSchemaDiscussion

一个相关的工作是JSON Schema ,它甚至有一些 IETF 标准化活动( draft-zyp-json-schema-03 - 用于描述 JSON 文档的结构和含义的 JSON 媒体类型

您可以将 YAML 文档作为dict加载并使用库架构来检查它:

from schema import Schema, And, Use, Optional, SchemaError
import yaml

schema = Schema(
        {
            'created': And(datetime.datetime),
            'author': And(str),
            'email': And(str),
            'description': And(str),
            Optional('tags'): And(str, lambda s: len(s) >= 0),
            'setup': And(list),
            'steps': And(list, lambda steps: all('=>' in s for s in steps), error='Steps should be array of string '
                                                                                  'and contain "=>" to separate'
                                                                                  'actions and expectations'),
            'teardown': And(list)
        }
    )

with open(filepath) as f:
   data = yaml.load(f)
   try:
       schema.validate(data)
   except SchemaError as e:
       print(e)

这些看起来不错。 yaml 解析器可以处理语法错误,这些库之一可以验证数据结构。

我处于同样的情况。 我需要验证 YAML 的元素。

首先,我认为“PyYAML 标签”是最好且简单的方法。 但后来决定使用“PyKwalify”,它实际上为 YAML 定义了一个架构。

PyYAML 标签:

YAML 文件有一个标签支持,我们可以通过为数据类型添加前缀来强制执行此基本检查。 (例如)对于整数 - !!int "123"

有关 PyYAML 的更多信息: http : //pyyaml.org/wiki/PyYAMLDocumentation#Tags这很好,但如果您要将其公开给最终用户,则可能会引起混淆。 我做了一些研究来定义 YAML 的模式。 这个想法就像我们可以使用其相应的架构来验证 YAML,以进行基本数据类型检查。 甚至我们的自定义验证(如 IP 地址、随机字符串)也可以添加到其中。 所以我们可以单独拥有我们的架构,让 YAML 简单易读。

我无法发布更多链接。 请 'google schema for YAM'L 查看架构讨论。

PyKwalify:

有一个名为 PyKwalify 的包可用于此目的: https ://pypi.python.org/pypi/pykwalify

这个包最符合我的要求。 我在本地设置中用一个小例子尝试了这个,并且正在工作。 这是示例架构文件。

#sample schema

type: map
mapping:
    Emp:
        type:    map
        mapping:
            name:
                type:      str
                required:  yes
            email:
                type:      str
            age:
                type:      int
            birth:
                type:     str

此架构的有效 YAML 文件

---
Emp:
    name:   "abc"
    email:  "xyz@gmail.com"
    age:    yy
    birth:  "xx/xx/xxxx"

谢谢

没有提到Pydantic

从他们的例子:

from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: Optional[datetime] = None
    friends: List[int] = []


# Parse your YAML into a dictionary, then validate against your model.
external_data = {
    'id': '123',
    'signup_ts': '2019-06-01 12:22',
    'friends': [1, 2, '3'],
}
user = User(**external_data)

您可以使用 python 的 yaml lib 来显示已加载文件的 message/char/line/file。

#!/usr/bin/env python

import yaml

with open("example.yaml", 'r') as stream:
    try:
        print(yaml.load(stream))
    except yaml.YAMLError as exc:
        print(exc)

错误信息可以通过 exc.problem 访问

访问exc.problem_mark以获取<yaml.error.Mark>对象。

此对象允许您访问属性

  • 姓名
  • 柱子
  • 线

因此,您可以创建自己的问题指针:

pm = exc.problem_mark
print("Your file {} has an issue on line {} at position {}".format(pm.name, pm.line, pm.column))

我包装了一些现有的与 json 相关的 python 库,目的是能够将它们与yaml一起使用

生成的python库主要包装...

  • jsonschema - 针对json-schema文件的json文件验证器,被包装以支持验证yaml文件对yaml格式的json-schema文件。

  • jsonpath-ng - python 的JSONPath实现,被包装以支持直接在yaml文件上选择JSONPath

...并且可以在github上找到:

https://github.com/yaccob/ytools

它可以使用pip安装:

pip install ytools

验证示例(来自https://github.com/yaccob/ytools#validation ):

import ytools
ytools.validate("test/sampleschema.yaml", ["test/sampledata.yaml"])

您还没有开箱即用的是针对yaml格式的外部模式进行验证。

ytools不提供任何以前不存在的东西——它只是使一些现有解决方案的应用更加灵活和方便。

我不知道 python 解决方案。 但是有一个用于 YAML 的 ruby​​ 模式验证器,称为kwalify 如果您没有遇到 python 库,您应该能够使用 subprocess 访问它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM