这可以相对容易地完成,并且无需更改输入文件。
自从
dict PyYAML 使用是硬编码的,不能打补丁,你不仅要提供
一个行为如你所愿的类 dict 类,你还必须通过箍来制作
PyYAML 使用该类。 IE。更改通常会构造 dict 的 SafeConstructor
要使用该新类,请将其合并到新的加载器中并使用 PyYAML 的 load 来使用该加载器:
import sys
import yaml
from yaml.loader import Reader, Scanner, Parser, Composer, SafeConstructor, Resolver
class MyDict(dict):
def __getattr__(self, name):
return self[name]
class MySafeConstructor(SafeConstructor):
def construct_yaml_map(self, node):
data = MyDict()
yield data
value = self.construct_mapping(node)
data.update(value)
MySafeConstructor.add_constructor(
u'tag:yaml.org,2002:map', MySafeConstructor.construct_yaml_map)
class MySafeLoader(Reader, Scanner, Parser, Composer, MySafeConstructor, Resolver):
def __init__(self, stream):
Reader.__init__(self, stream)
Scanner.__init__(self)
Parser.__init__(self)
Composer.__init__(self)
MySafeConstructor.__init__(self)
Resolver.__init__(self)
yaml_str = """\
a: 1
b:
- q: "foo"
r: 99
s: 98
- x: "bar"
y: 97
z: 96
c:
d: 7
e: 8
f: [9,10,11]
"""
mydict = yaml.load(yaml_str, Loader=MySafeLoader)
print(mydict.b[0].r)
给出:
99
如果您需要能够处理 YAML1.2,您应该使用 ruamel.yaml
(免责声明:我是该软件包的作者)这使得上述内容稍微简单
import ruamel.yaml
# same definitions for yaml_str, MyDict
class MySafeConstructor(ruamel.yaml.constructor.SafeConstructor):
def construct_yaml_map(self, node):
data = MyDict()
yield data
value = self.construct_mapping(node)
data.update(value)
MySafeConstructor.add_constructor(
u'tag:yaml.org,2002:map', MySafeConstructor.construct_yaml_map)
yaml = ruamel.yaml.YAML(typ='safe')
yaml.Constructor = MySafeConstructor
mydict = yaml.load(yaml_str)
print(mydict.b[0].r)
这也给出了:
99
(如果您的实际输入很大,加载数据的速度应该会明显更快)