共计 2094 个字符,预计需要花费 6 分钟才能阅读完成。
指标
- 读写 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:
正文完