gpt4 book ai didi

python - 解析和验证 YAML 配置文件的最佳方式

转载 作者:太空宇宙 更新时间:2023-11-04 00:32:59 27 4
gpt4 key购买 nike

我们有一个在 YAML 中存储设置的项目(设置文件由 ansible 脚本生成)。现在我们使用 pyyaml 来解析 YAML 格式,使用 marshmallow 来验证设置。我很高兴在 YAML 中存储设置,但我不认为 marshmellow 是我需要的工具(模式很难阅读,我不需要设置的序列化,想要 xsd 之类的东西)。那么在项目中验证设置的最佳实践是什么,也许有独立于语言的方式? (我们使用的是 python 2.7)

YAML 设置:

successive:
worker:
cds_process_number: 0 # positive integer or zero
spider_interval: 10 # positive integer
run_worker_sh: /home/lmakeev/CDS/releases/master/scripts/run_worker.sh # OS path
allow:
- "*" # regular expression
deny:
- "^[A-Z]{3}_.+$" # regular expression

最佳答案

模式描述是一种自己的语言,具有您必须学习的自己的语法和特性。如果您的要求发生变化,您必须维护其验证 YAML 的“程序”。

如果您已经在使用 YAML 并熟悉 Python,则可以使用 YAML 的标记工具在解析时检查对象。

假设你有一个文件input.yaml:

successive:
worker:
cds_process_number: !nonneg 0
spider_interval: !pos 10
run_worker_sh: !path /home/lmakeev/CDS/releases/master/scripts/run_worker.sh
allow:
- !regex "*"
deny:
- !regex "^[A-Z]{3}_.+$"

(您的示例文件删除了注释并插入了标签),您可以使用以下程序创建并注册四个检查值的类:

import sys
import os
import re
import ruamel.yaml
import pathlib

class NonNeg:
yaml_tag = u"!nonneg"

@classmethod
def from_yaml(cls, constructor, node):
val = int(node.value) # this creates/returns an int
assert val >= 0
return val

class Pos(int):
yaml_tag = u"!pos"

@classmethod
def from_yaml(cls, constructor, node):
val = cls(node.value) # this creates/return a Pos()
assert val > 0
return val

class Path:
yaml_tag = u"!path"

@classmethod
def from_yaml(cls, constructor, node):
val = pathlib.Path(node.value)
assert os.path.exists(val)
return val


class Regex:
yaml_tag = u"!regex"
def __init__(self, val, comp):
# store original string and compile() of that string
self._val = val
self._compiled = comp

@classmethod
def from_yaml(cls, constructor, node):
val = str(node.value)
try:
comp = re.compile(val)
except Exception as e:
comp = None
print("Incorrect regex", node.start_mark)
print(" ", node.tag, node.value)
return cls(val, comp)


yaml = ruamel.yaml.YAML(typ="safe")
yaml.register_class(NonNeg)
yaml.register_class(Pos)
yaml.register_class(Path)
yaml.register_class(Regex)

data = yaml.load(pathlib.Path('input.yaml'))

单个 from_yaml 类方法中的实际检查应根据您的需要进行调整(我不得不删除路径的断言,因为我没有该文件)。

如果您运行上面的代码,您会注意到它会打印:

Incorrect regex   in "input.yaml", line 7, column 9
!regex *

因为 "*" 不是有效的正则表达式。您的意思是:".*"


¹ 这是使用 ruamel.yaml 完成的,一个 YAML 1.2 解析器,我是它的作者。您可以使用 PyYAML 实现相同的结果,例如通过子类化 ObjectDict(默认情况下是不安全的,因此请确保在您的代码中更正它)

关于python - 解析和验证 YAML 配置文件的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45147784/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com