问题在于,在 的 API 边界上yaml.load
,源的所有代表性信息都已丢失。Validate
得到一个 Python dict 并且不知道它来自哪里,而且 dict 不包含此信息。
但是,您可以自己实现它。voluptuous'Invalid
错误带有一个path
要遵循的键列表。有了这个路径,您可以再次将 YAML 解析为节点(携带表示信息)并发现项目的位置:
import yaml
def line_from(path, yaml_input):
node = yaml.compose(yaml_input)
for item in path:
for entry in node.value:
if entry[0].value == item:
node = entry[1]
break
else: raise ValueError("unknown path element: " + item)
return node.start_mark.line
# demostrating this on more complex input than yours
data = """
spam:
egg:
sausage:
spam
"""
print(line_from(["spam", "egg", "sausage"], data))
# gives 4
有了这个,你就可以做到
try:
data = Validate(yaml.load(StringIO(data)))
except Invalid as e:
line = line_from(e.path, data)
path = "data." + ".".join(e.path)
print(f"Error: validation failed on line {line} ({path}): {e.error_message}")
我会为这个答案走这么远,因为它向您展示了如何发现错误的起源行。您可能需要将其扩展到:
- 处理 YAML 序列(我的代码假设每个中间节点都是 a
MappingNode
, aSequenceNode
将在其列表中有单个节点value
而不是键值元组)
MultipleInvalid
为每个内部错误发出消息的句柄
expected int
如果你真的想重写should be an integer
(不知道你会怎么做)
- 打印错误后中止