pyyaml 和 yaml 子级别
pyyaml and yaml sublevels
我正在尝试使用 PyYAML 将 YAML 文件解析为 python 对象
不过我在课程中提出了疑问
我有 YAML 文件
first_lvl:
second_lvl:
item_a:
- value_a : "value aaa"
- value_b : "value bbb"
我的 python 脚本读取 YAML 并将其加载到对象中
import yaml
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
with open(job_file.yml) as f:
skeleton = yaml.full_load(f)
MyJob = Struct(**skeleton)
print(MyJob.first_lvl)
这很好,但仅适用于 YAML 的第一级。如果我想达到应该包含在对象中的 yaml 文件的子级值怎么样
像这样:
print(MyJob.first_lvl.second_lvl)
它可能与 PyYAML 模块无关,更多的是 python 处理对象的方式,但我还是迷路了
任何人都可以开灯吗?
在您的评论中,您表示希望只有一个
Struct
实例已加载。但是,如果您想访问该值
"value aaa"
通过写作
my_job.first_lvl.second_lvl.item_a.0.value_a
,你不能这样做
通过提供 __getattr__
方法,因为这会引发错误
说明 dict
对象没有 second_lvl
属性(它只是
有一个键 second_lvl
)。 __getattr__
永远不会被调用,因为,
在 Struct
实例上,属性查找不会失败。
你可以做的是提供一些方法 lookup
作为参数采用 "dotted" 字符串:
import ruamel.yaml
yaml_str = """\
first_lvl:
second_lvl:
item_a:
- value_a : "value aaa"
- value_b : "value bbb"
"""
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
def lookup(self, s):
def recurse(d, names):
name = names[0]
if isinstance(d, list): # list indices cannot be strings
name = int(name)
if len(names) > 1:
return recurse(d[name], names[1:])
return d[name]
names = s.split('.')
return recurse(getattr(self, names[0]), names[1:])
yaml = ruamel.yaml.YAML(typ='safe')
my_job = Struct(**yaml.load(yaml_str))
print(my_job.lookup("first_lvl.second_lvl.item_a.0.value_a"))
给出:
value aaa
显示了另一种扩展
在往返模式下使用 ruamel.yaml 时的默认数据结构。
如果你真的想写
my_job.first_lvl.second_lvl.item_a.0.value_a
,没有引号,我
不认为有办法让每个级别都意识到看
上属性。这意味着扩展 Struct
,所以
class 可以从映射 和 序列构造。那可以做到
在加载 YAML 之后,但 IMO 最好在构建 YAML 期间完成。
我正在尝试使用 PyYAML 将 YAML 文件解析为 python 对象
不过我在课程中提出了疑问
我有 YAML 文件
first_lvl:
second_lvl:
item_a:
- value_a : "value aaa"
- value_b : "value bbb"
我的 python 脚本读取 YAML 并将其加载到对象中
import yaml
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
with open(job_file.yml) as f:
skeleton = yaml.full_load(f)
MyJob = Struct(**skeleton)
print(MyJob.first_lvl)
这很好,但仅适用于 YAML 的第一级。如果我想达到应该包含在对象中的 yaml 文件的子级值怎么样
像这样:
print(MyJob.first_lvl.second_lvl)
它可能与 PyYAML 模块无关,更多的是 python 处理对象的方式,但我还是迷路了
任何人都可以开灯吗?
在您的评论中,您表示希望只有一个
Struct
实例已加载。但是,如果您想访问该值
"value aaa"
通过写作
my_job.first_lvl.second_lvl.item_a.0.value_a
,你不能这样做
通过提供 __getattr__
方法,因为这会引发错误
说明 dict
对象没有 second_lvl
属性(它只是
有一个键 second_lvl
)。 __getattr__
永远不会被调用,因为,
在 Struct
实例上,属性查找不会失败。
你可以做的是提供一些方法 lookup
作为参数采用 "dotted" 字符串:
import ruamel.yaml
yaml_str = """\
first_lvl:
second_lvl:
item_a:
- value_a : "value aaa"
- value_b : "value bbb"
"""
class Struct:
def __init__(self, **entries):
self.__dict__.update(entries)
def lookup(self, s):
def recurse(d, names):
name = names[0]
if isinstance(d, list): # list indices cannot be strings
name = int(name)
if len(names) > 1:
return recurse(d[name], names[1:])
return d[name]
names = s.split('.')
return recurse(getattr(self, names[0]), names[1:])
yaml = ruamel.yaml.YAML(typ='safe')
my_job = Struct(**yaml.load(yaml_str))
print(my_job.lookup("first_lvl.second_lvl.item_a.0.value_a"))
给出:
value aaa
如果你真的想写
my_job.first_lvl.second_lvl.item_a.0.value_a
,没有引号,我
不认为有办法让每个级别都意识到看
上属性。这意味着扩展 Struct
,所以
class 可以从映射 和 序列构造。那可以做到
在加载 YAML 之后,但 IMO 最好在构建 YAML 期间完成。