Python 读写和解析 YAML 文件格式
Posted songofhawk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 读写和解析 YAML 文件格式相关的知识,希望对你有一定的参考价值。
目标
- 读写API简单
- 解析出来的数据结构易处理
- 支持对象的序列化/反序列化
库
一个比较好用的库是ruamel,需要安装一下:
pip install ruamel.yaml
然后代码中导入即可:
from ruamel.yaml import YAML
但导入的YAML是个类,真正用的时候,需要创建一个实例yaml = YAML()
读写文件
准备一个配置文件:
id: 100
name: "测试项目"
version: "3.1"
steps:
- id: 18
action: "Prepare"
expects:
- id: 238,
result: GOOD
- id: 239,
result: PERFECT
读
代码中首先需要自行打开文件,然后把文件对象传给yaml实例:
with open(conf_file) as f:
data = yaml.load(f)
for k, v in data.items():
cls.handle_value(data, k, v)
conf = yaml.load(f)
这里遍历load后的结果,然后通过业务函数(handle_value)自行处理的。
写
写和读的代码类似,还是自行用写模式打开文件,然后把一个dict/list嵌套结构的对象,传给dump函数即可
with open(conf_file, \'w\') as f:
the_list = []
for step in self.steps:
the_list.append(step.to_dict())
documents = yaml.dump(the_list, f)
例子里最外层对象是list,替换成dict也没有问题,总之需要是可枚举内容的对象。
序列化/反序列化
ruamel本身提供序列化/反序列化支持:
- 首先,给需要序列化的类,加上yaml_object注解
- 添加一个yaml_tag类属性,作为序列化前缀
- 给这个类添加to_yaml和from_yaml两个类方法,分别处理序列化,和反序列化
示例如下:
@yaml_object(yaml)
class ScreenRect(dict):
yaml_tag = u\'!rect\'
def __init__(self, left: int = None, right: int = None, top: int = None, bottom: int = None):
# super(ScreenRect, self).__init__([left, right, top, bottom])
# self._inner_list = [left, right, top, bottom]
self[\'l\'] = left
self[\'r\'] = right
self[\'t\'] = top
self[\'b\'] = bottom
@property
def left(self):
return self[\'l\']
@property
def right(self):
return self[\'r\']
@property
def top(self):
return self[\'t\']
@property
def bottom(self):
return self[\'b\']
def __str__(self):
return \'l:{}, r:{}, t:{}, b:{}\'.format(self.left, self.right, self.top, self.bottom)
@classmethod
def to_yaml(cls, representer, node):
return representer.represent_scalar(cls.yaml_tag,
\'l:{}, r:{}, t:{}, b:{}\'.format(node.left, node.right, node.top,
node.bottom))
# return {\'l\': self.left, \'r\': self.right, \'t\': self.top, \'b\': self.bottom}
@classmethod
def from_yaml(cls, constructor, node):
splits = node.value.split(\', \')
# test = list(map(lambda x: x + \'_sss\', splits))
v = list(map(lambda x: x[1], map(methodcaller("split", ":"), splits)))
# print(v)
return cls(left=int(v[0]), right=int(v[1]), top=int(v[2]), bottom=int(v[3]))
上例中,ScreenRect类是dict子类,但希望序列化的时候,按特定格式生成字符串,所以在to_yaml中做了包装,几个property的定义只是为了以后ScreenRect类实例方便读写数据,并不是必须的。生成以后的数据,类似下面这个样子:
rect: !rect l:1415, r:1805, t:239, b:609
中文字符
一开始使用的时候,发现utf-8编码的配置文件无法被读取,还以为ruamel不支持,后来发现是自己代码的问题,只需要打开文件的时候,指定编码就可以了:
with open(conf_file, encoding=\'utf-8\') as f:
以上是关于Python 读写和解析 YAML 文件格式的主要内容,如果未能解决你的问题,请参考以下文章