超级讨厌这种格式,还有python的空格语法也是比较恶心。
yml的问题,跟当前很多程序员的问题一样,就是追求假的简洁。
真正的简洁,是可读性可维护性都很高,是一种主观感受的评判。假的简洁,是看上去字少就是简洁,但引入一堆更严重的问题。
谁和我说 yaml 简洁好写我打爆谁的狗头
只能说不知道是哪个大聪明想到 CI 用 yaml 写, 这东西看的简直让人吐血.
还有 swagger 的地狱 yml, 我总是在想他们写这玩意儿的时候自己不会呕吐吗?
天下苦 yaml 久矣, 我并非不喜欢缩进
只有 2-6 层嵌套的时候用缩进是合理的
当有 4-8 层嵌套的时候, 缩进可读性就直线下降了, 用括号括起来是合理的
当有 6 层以上嵌套的时候, 不如想想要不要用 XML, 头尾写两遍才是合理的
热知识, 世界上没有任何一个库能通过 yaml1.2 的所有 test suites 并拒绝掉所有错误输入.
行末空格。卒
文末空行。卒
迷之编码。卒
和JSON还有一比,提XML是嫌尖括号还没写过瘾吗?
说yaml不好用可以理解,但是说json,xml好是什么鬼?
xml像裹脚布一样的啰嗦,好用在哪里?
json的每个属性都要加引号,累不累?多打一个逗号就报错,也不能加注释,这玩意适合人写?
推荐2种配置文件格式,好不好用自行判断
title = “TOML Example”
[owner] name = “Tom Preston-Werner” dob = 1979-05-27T07:32:00-08:00
[database] enabled = true ports = [ 8000, 8001, 8002 ] data = [ [“delta”, “phi”], [3.14] ] temp_targets = { cpu = 79.5, case = 72.0 }
[servers]
[servers.alpha] ip = “10.0.0.1” role = “frontend”
[servers.beta] ip = “10.0.0.2” role = “backend”
讯享网# This is a HJSON document { // use #, // or // comments, // omit quotes for keys key: 1 // omit quotes for strings contains: everything on this line // omit commas at the end of a line cool: {
foo: 1 bar: 2
} // allow trailing commas list: [
讯享网1, 2,
] // and use multiline strings realist:
''' My half empty glass, I will fill your empty half. Now you are half full. '''
}
说yaml友好的,肯定没踩过yaml格式的雷的
踩雷,是yaml独一无二的特色
2023 年了,考虑一下 toml ?
猜猜下面的内容是不是合法 yaml
讯享网{ a: “question”, b: “answer” }
还有下面的内容,你猜是 yaml 还是 json?
{
讯享网"sites": [ { "name":"菜鸟教程" , "url":"www.runoob.com" }, { "name":"google" , "url":"www.google.com" }, { "name":"微博" , "url":"www.weibo.com" } ]
}
在 yaml的验证网站里面,将上面那个 json 数据复制进去,然后就会成功被验证,并且还能被格式化。。。。
讯享网
甚至这样搞,都可以:
所以,为什么会觉得 xml 不错?
不正经回答问题。我只想再加入一种格式参加比烂大赛!
我觉得吧,所谓YAML“不友好”、“很难理解”其实是pyyaml默认输出格式的锅。
我之前用YAML格式存储分子力场文件,举个例子,对于一个水分子模板来说,使用yaml.dump()保存出来文件长这样:
template: WAT: atom_name: - O - H1 - H2 atom_type: - OW - HW - HW atom_mass: - 16.00 - 1.008 - 1.008 atomic_number: - 8 - 1 - 1 atom_charge: - -0.834 - 0.417 - 0.417 atom_type: - OW - HW - HW bond: - - 0 - 1 - - 0 - 2 molecule: residue: - WAT length_unit: nm coordinate: - - 0.0 - 0.0 - 0.0 - - 0.031521 - 0.063173 - 0.0 - - -0.031521 - 0.063173 - 0.0
当时我看到输出的文件就想吐槽,这TM什么鬼,文件怎么这么长?一个水分子才三个原子而已都已经这么长了,另外一个用来存蛋白质力场的文件居然长达8000+行。
而且这个文件的可读性也很差,比如键(bond)就应该是一对一对的,而坐标(coordinate)就应该是个N*3的二维数组,所以为啥每个数都要换行?
我当时一度想要放弃YAML改用JSON,最起码JSON文件没这么长,但是JSON那一堆大括号我看着也烦。
但是后来有一次我代码写的有点bug,有几个地方输出了空的list,结果我在输出文件里面看到一个方括号[]。这个时候我才知道,原来YAML格式是支持用方括号表示数组的啊。不但如此,我又从查了一下,原来YAML格式不但可以用方括号表示list,还可以用花括号{}表示dict。
于是我将上面的那个文件改成了这样的格式:
讯享网template: WAT: atom_name: [O, H1, H2] atom_type: [OW, HW, HW] atom_mass: [16.00, 1.008, 1.008] atomic_number: [8, 1, 1] atom_charge: [-0.834, 0.417, 0.417] bond: - [0, 1] - [0, 2] molecule: residue: - WAT length_unit: nm coordinate: - [0.0, 0.0, 0.0] - [0.0, 0.0, 0.0] - [-0.0, 0.0, 0.0]
嗯,这样不就很好了嘛!无论是可读性还是长度都很不错。
不过有个问题在于,直接使用yaml.dump进行输出貌似是没办法搞成我弄的这个的样子,我又不可能手工去修改每个一个文件。
不过这倒难不倒我,我用了一个“奇技淫巧”就解决了这个问题:那就是把不想换行的list或dict先转换成str,比如template[‘WAT’][‘atom_name’]=str(template[‘WAT’][‘atom_name’]),这样YAML格式的就会把这个list或dict以字符串的形式进行输出:
atom_name: ‘[’‘O’‘, ’‘H1’‘, ’‘H2’‘]’
这样的话会多出一堆单引号,所以不要直接用yaml.dump输出为文件,而是先用yaml.dump把整个字典转换为一个字符串,然后删掉字符串里面的单引号,再输出为文本文件就好了:
讯享网temp_yaml = yaml.dump(template).replace(“‘”,“”) with open(’template.yaml‘, ’w‘, encoding=“utf-8”) as file:
<span class="n">file</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">temp_yaml</span><span class="p">)</span></code></pre></div><p data-pid="EAHkLqAG">经过这样的处理,之前那个8000+行的文件就变成只有不到两千行,我对这样的结果已经相当满意了。</p><p data-pid="XbHuaUmI">所以说其实YAML格式本身完全可以写的很友好,只不过pyyaml默认的输出格式实在是太反人类了。如果pyyaml的输出格式可以更容易地自定义,那就会让YAML文件好看很多。</p>
我 TM 从 2006年使用 ROR 就在用 yaml 做配置,内心就对这玩意吐槽得不行,巨难用,什么破B玩意。
大家都回答了很多了,具体就懒得再说了。
这两年国外搞 PHP 的不知道吃错了什么药,都转用 yaml 来做项目配置,真的无语。php 文件本身就是很好的配置文件了,而且支持编程化处理,关键词、函数、全局常量还能吃到编辑器智能提示的红利。
现在流行用 yaml 做 CI,丫的真难用,什么狗屁玩意。然后国内也跟着学,比如 gitee,真 TM 难用,连个玩意都算不上,就是一个屁。
因为很早就接触 JSON-Schema,所以我是坚定的 JSON 党。
JAVA开发,挺讨厌yaml,我宁愿用properties。
1、多个空格,少个空格,就会导致无法解析。
2、一坨坨的递进关系,看着挺有层级,其实并没有好到哪去。
3、对于运维人员就是噩梦,毕竟人家不是开发,用properties时,就是个体力活,多写几行配置,用yaml之后问题就出来,层级不对或者少个空格,就跟找茬一样。
大伙都用 json 不好吗。。。这些配置相互都是可替代的,留一个就行了,我选 json。
实在是不想把用途上没有区别的东西学三遍,累。
吹吹json就行了,XML这种存起来废硬盘打印出来废纸废墨看起来废眼废脑子的东西,我都怀疑是ETO发明用来毁灭计算机行业的。
说实话迄今为止我都无法理解设计ML语言的人到底是个啥脑回路。
我对yaml和对python的评价一样,仅基于缩进的结构是逆天。
因为基于缩进的结构实际上并不能帮助程序员更好得发现和排除错误,反而阻碍了parser帮助程序员检查错误的可能性。因为程序员很容易写出错误的缩进,但并不容易写出错误的开始/结束标签,相反parser可以通过formatter纠正缩进错误,这有助于程序员通过判断缩进输出是否符合预期来判断开始/结束标签是否正确。
然而缩进是你手写的这一事实会影响你对缩进的预期,而仅基于缩进的结构阻碍了parser对缩进的修正,因为parser无从得知“正确”缩进是什么。这使得你难以通过检查parser输出的缩进错误检查结构错误,从而减少了一个快速发现错误的途径。
什么?你说你写不来开始/结束标签?那菜就多练好吧。编译器成功得帮你阻止一段有问题的代码上线你不给磕一个就算了,还要嫌它碍事那就是你的不对了。
yaml简直是反人类的东西,这玩意我第一眼看到还以为是上个世纪淘汰的产物
最优雅的还是json,但json不能写注释
所以一个支持json语法且能够写注释的配置文件类型,这才是程序员真正需要的玩意
YAML 并不是一种新奇的语言,YAML 首次发表于 2001 年,距离现在已经过去差不多 20 个年头。YAML 虽然不如 JSON、XML 之类的语言流行,应用也没有那么广泛,但是 YAML 也有它的优势。
互联网上的关于 YAML 的文章虽然不多,但也足以让人了解这一款语言,那我为什么还要写这一片入门文章呢?
我认为现有的文章有以下几点不足:
- 内容碎片化,阅读起来不够流畅
- 讲解较为生硬,阅读起来比较费劲
- 缺少对比,难以让人快速理解
所以本篇文章的主要目的就是让读者能够快速并准确地了解这款语言,事不宜迟,让我们开始吧!
为了帮助理解,我将在文中穿插相对应的 JSON 格式的内容作为对比。
可能是东半球最通俗易懂的 YAML 中文讲解之一(手动狗头)
YAML 是一种较为人性化的数据序列化语言,可以配合目前大多数编程语言使用。
YAML 的语法比较简洁直观,特点是使用空格来表达层次结构,其最大优势在于数据结构方面的表达,所以 YAML 更多应用于编写配置文件,其文件一般以 .yml 为后缀。
YAML 目前的官方全称为 “ YAML Ain’t Markup Language(YAML 不是标记语言)”,但有意思的是,其实 YAML 最初的含义是 “ Yet Another Markup Language(还是一种标记语言)”。
目前 YAML 的最新版本为 1.2(第三个版本),本文将以 YAML 1.2 的标准进行讲解。
- 就是字面上的意思
讯享网One: 1 one: 2
- 缩进只能使用空格,不能用 TAB 字符
- 缩进的空格数量不重要,但是同一层级的元素左侧必须对齐
# YAML one: two: 2 three: four: 4 five: 5 // 以上的内容转成 JSON 后 “one”: { “two”: 2, “three”: { “four”: 4, “five”: 5 } }
- 只支持单行注释
讯享网# 我是注释 # 我也是注释
- 用“ — ”即三个破折号表示一份内容的开始
- 用“ … ”即三个小数点表示一份内容的结束(非必需)
— # 这是第一份内容 one: 1 # 其他内容… … — # 这是第二份内容 two: 2 # 其他内容…
表示以键值对(key: value)形式出现的数据
- 使用“冒号+空格”来分开键与值
讯享网# YAML key: value // JSON “key”: “value”
- 支持多层嵌套(用缩进表示层级关系)
# YAML key: child-key1: value1 child-key2: value2 // JSON “key”: { “child-key1”: “value1”, “child-key2”: “value2”, }
- 支持流式风格( Flow style)的语法(用花括号包裹,用逗号加空格分隔,类似 JSON)
讯享网# YAML key: { child-key1: value1, child-key2: value2 } // JSON “key”: { “child-key1”: “value1”, “child-key2”: “value2” }
- 使用问号“?”声明一个复杂对象,允许你使用多个词汇(数组)来组成键
# YAML ?
- keypart1 - keypart2 : - value1 - value2
- 一组以区块格式(Block Format)(即“破折号+空格”)开头的数据组成一个数组
讯享网
# YAML values: - value1 - value2 - value3 // JSON “values”: [ “value1”, “value2”, “value3” ]- 同时也支持内联格式(Inline Format)来表达(用方括号包裹,逗号加空格分隔,类似 JSON)
# YAML values: [value1, value2, value3] // JSON “values”: [ “value1”, “value2”, “value3” ]- 支持多维数组(用缩进表示层级关系)
讯享网
# YAML values: - - value1 - value2 - - value3 - value4 // JSON “values”: [ [ “value1”, “value2”], [“value3”, “value4”] ]表示 YAML 中最基本的数据类型
- 字符串一般不需要用引号包裹,但是如果字符串中使用了反斜杠“\”开头的转义字符就必须使用引号包裹
# YAML strings: - Hello without quote # 不用引号包裹 - Hello world # 拆成多行后会自动在中间添加空格 - ‘Hello with single quotes’ # 单引号包裹 - “Hello with double quotes” # 双引号包裹 - “I am fine. \u263A” # 使用双引号包裹时支持 Unicode 编码 - “\x0d\x0a is \r\n” # 使用双引号包裹时还支持 Hex 编码 - ‘He said: “Hello!”’ # 单双引号支持嵌套“ // JSON ”strings“: [ ”Hello without quote“, ”Hello world“, ”Hello with single quotes“, ”Hello with double quotes“, ”I am fine. ☺“, ”\r\n is \r\n“, ”He said: ‘Hello!’“ ]- 对于多行的文字,YAML 提供了两种特殊的语法支持
保留换行(Newlines preserved)
使用 竖线符“ | ”来表示该语法,每行的缩进和行尾空白都会被去掉,而额外的缩进会被保留
讯享网
# YAML lines: | 我是第一行 我是第二行 我是吴彦祖 我是第四行 我是第五行 // JSON ”lines“: ”我是第一行\n我是第二行\n 我是吴彦祖\n 我是第四行\n我是第五行“折叠换行(Newlines folded)
使用 右尖括号“ > ”来表示该语法,只有空白行才会被识别为换行,原来的换行符都会被转换成空格
# YAML lines: > 我是第一行 我也是第一行 我仍是第一行 我依旧是第一行 我是第二行 这么巧我也是第二行 // JSON ”lines“: ”我是第一行 我也是第一行 我仍是第一行 我依旧是第一行\n我是第二行 这么巧我也是第二行“- “true”、“True”、“TRUE”、“yes”、“Yes”和“YES”皆为真
- “false”、“False”、“FALSE”、“no”、“No”和“NO”皆为假
讯享网
# YAML boolean: - true # True、TRUE - yes # Yes、YES - false # False、FALSE - no # No、NO // JSON ”boolean“: [ true, true, false, false ]- 支持二进制表示
# YAML int: - 666 - 00010000 # 二进制表示 // JSON ”int“: [ 666, 4096 ]- 支持科学计数法
讯享网
# YAML float: - 3.14 - 6.e+5 # 使用科学计数法 // JSON ”float“: [ 3.14, .15 ]- “null”、“Null”和“”都是空,不指定值默认也是空
# YAML nulls: - null - Null - - // JSON ”nulls“: [ null, null, null, null ]- YAML 也支持 ISO 8601 格式的时间数据
这里使用 JavaScript 对象进行对比
讯享网
# YAML date1: 2020-05-26 date2: 2020-05-26T01:00:00+08:00 dete3: 2020-05-26T02:00:00.10+08:00 date4: 2020-05-26 03:00:00.10 +8 // JavaScript date1: Tue May 26 2020 08:00:00 GMT+0800 (中国标准时间), date2: Tue May 26 2020 01:00:00 GMT+0800 (中国标准时间), dete3: Tue May 26 2020 02:00:00 GMT+0800 (中国标准时间), date4: Tue May 26 2020 03:00:00 GMT+0800 (中国标准时间)- YAML 支持使用严格类型标签“!!”(双感叹号+目标类型)来强制转换类型
# YAML a: !!float ‘666’ # !! 为严格类型标签 b: ‘666’ # 其实双引号也算是类型转换符 c: !!str 666 # 整数转为字符串 d: !!str 666.66 # 浮点数转为字符串 e: !!str true # 布尔值转为字符串 f: !!str yes # 布尔值转为字符串 // JSON ”a“: 666, ”b“: ”666“, ”c“: ”666“, ”d“: ”666.66“, ”e“: ”true“ ”f“: ”yes“YAML 也可以使用一些更高级的类型,但是并不一定兼容所有解析器,包括集合(Sets)、有序映射(Ordered Map)、十六进制数据(Hexdecimal)和二进制数据(Binary)。
本文将不会对这几种类型进行讲解,感兴趣的读者可以自行搜索研究。
- 为了保持内容的简洁,避免过多重复的定义,YAML 提供了由锚点标签“&”和引用标签“*”组成的语法,利用这套语法可以快速引用相同的一些数据…
讯享网
# YAML a: &anchor # 设置锚点 one: 1 two: 2 three: 3 b: *anchor # 引用锚点 // JSON ”a“: { ”one“: 1, ”two“: 2, ”three“: 3 }, ”b“: { ”one“: 1, ”two“: 2, ”three“: 3 }- 配合合并标签“<<”使用可以与任意数据进行合并,你可以把这套操作想象成面向对象语言中的继承…
# YAML human: &base # 添加名为 base 的锚点 body: 1 hair: 999 singer: <<: *base # 引用 base 锚点,实例化时会自动展开 skill: sing # 添加额外的属性 programer: <<: *base # 引用 base 锚点,实例化时会自动展开 hair: 6 # 覆写 base 中的属性 skill: code # 添加额外的属性 // JSON ”human“: { ”body“: 1, ”hair“: 999 }, ”singer“: { ”body“: 1, ”hair“: 999, ”skill“: ”sing“ }, ”programer“: { ”body“: 1, ”hair“: 6, ”skill“: ”code“ }
- YAML 官方网站 https://yaml.org
- YAML 1.2 官方文档 https://yaml.org/spec/1.2/spec.html
- YAML - 维基百科 https://zh.wikipedia.org/wiki/YAML
- YAML to JSON (格式在线转换) https://www.json2yaml.com/convert-yaml-to-json
微信推文版本
个人博客:菜鸟小栈
开源主页:陈皮皮
Eazax-CCC 游戏开发脚手架
多平台通用的屏幕分辨率适配方案
围绕物体旋转的方案以及现成的组件
一个全能的挖孔 Shader
一个开源的自动代码混淆插件
微信小游戏接入好友排行榜(开放数据域)
为什么选择使用 TypeScript ?
高斯模糊 Shader
以上内容皆为陈皮皮的个人观点。
文采不佳,如果写得不好还请各位多多包涵。如果有哪些地方说的不对,还请各位指出,希望与大家共同进步。
接下来我会持续分享自己所学的知识与见解,欢迎各位关注本公众号。
我们,下次见!
专注但不仅限于游戏开发、前端和后端技术。虽不高产,但是每一篇原创都非常用心!
”> Input and output.
YAML是一种直观的能够被电脑识别的的数据序列化格式,容易被人类阅读,并且容易和脚本语言交互。YAML类似于XML,但是语法比XML简单得多,对于转化成数组或可以hash的数据时是很简单有效的。
1、load() :返回一个对象 我们先创建一个yml文件,config.yml:
讯享网
name: Tom Smith age: 37 spouse: name: Jane Smith age: 25 children: - name: Jimmy Smith age: 15 - name1: Jenny Smith age1: 12读取yml文件:
import yaml f = open(r‘E:\AutomaticTest\Test_Framework\config\config.yml’) y = yaml.load(f) print (y)结果:
讯享网
{‘name’: ‘Tom Smith’, ‘age’: 37, ‘spouse’: {‘name’: ‘Jane Smith’, ‘age’: 25}, ‘children’: [{‘name’: ‘Jimmy Smith’, ‘age’: 15}, {‘name1’: ‘Jenny Smith’, ‘age1’: 12}]}2、load_all()生成一个迭代器 如果string或文件包含几块yaml文档,你可以使用yaml.load_all来解析全部的文档。
import yaml f = ‘’‘ — name: James age: 20 — name: Lily age: 19 ’‘’ y = yaml.load_all(f) for data in y: print(data)执行结果:
讯享网
{‘name’: ‘James’, ‘age’: 20} {‘name’: ‘Lily’, ‘age’: 19}3、yaml.dump 将一个python对象生成为yaml文档
import yaml aproject = {‘name’: ‘Silenthand Olleander’, ‘race’: ‘Human’, ‘traits’: [‘ONE_HAND’, ‘ONE_EYE’] }
print(yaml.dump(aproject,))
执行结果:
讯享网name: Silenthand Olleander race: Human traits: [ONE_HAND, ONE_EYE]
yaml.dump接收的第二个参数一定要是一个打开的文本文件或二进制文件,yaml.dump会把生成的yaml文档写到文件里
import yaml
aproject = {‘name’: ‘Silenthand Olleander’,
讯享网 <span class="s1">'race'</span><span class="p">:</span> <span class="s1">'Human'</span><span class="p">,</span> <span class="s1">'traits'</span><span class="p">:</span> <span class="p">[</span><span class="s1">'ONE_HAND'</span><span class="p">,</span> <span class="s1">'ONE_EYE'</span><span class="p">]</span> <span class="p">}</span>
f = open(r‘E:\AutomaticTest\Test_Framework\config\config.yml’,‘w’) print(yaml.dump(aproject,f))
4、yaml.dump_all()将多个段输出到一个文件中
import yaml
obj1 = {“name”: “James”, “age”: 20} obj2 = [“Lily”, 19]
with open(r‘E:\AutomaticTest\Test_Framework\config\config.yml’, ‘w’) as f:
讯享网<span class="n">yaml</span><span class="o">.</span><span class="n">dump_all</span><span class="p">([</span><span class="n">obj1</span><span class="p">,</span> <span class="n">obj2</span><span class="p">],</span> <span class="n">f</span><span class="p">)</span></code></pre></div><p data-pid="csuTgktr">输出到文件:</p><div class="highlight"><pre><code class="language-python3"><span class="p">{</span><span class="n">age</span><span class="p">:</span> <span class="mi">20</span><span class="p">,</span> <span class="n">name</span><span class="p">:</span> <span class="n">James</span><span class="p">}</span>
— [Lily, 19]
1、基本规则
1. 大小写敏感 2. 使用缩进表示层级关系 3. 缩进时不允许使用Tab,只允许使用空格 4. 缩进的空格数目不重要,只要相同层级的元素左对齐即可 5. # 表示注释,从它开始到行尾都被忽略
2、yaml转字典 yaml中支持映射或字典的表示,如下:
讯享网# 下面格式读到Python里会是个dict name: 灰蓝 age: 0 job: Tester
输出:
{‘name’: ‘灰蓝’, ‘age’: 0, ‘job’: ‘Tester’}
3、yaml转列表 yaml中支持列表或数组的表示,如下:
讯享网# 下面格式读到Python里会是个list - 灰蓝 - 0 - Tester
输出:
[‘灰蓝’, 0, ‘Tester’]
4、复合结构: 字典和列表可以复合起来使用,如下:
讯享网# 下面格式读到Python里是个list里包含dict - name: 灰蓝 age: 0 job: Tester - name: James age: 30
输出:
[{‘name’: ‘灰蓝’, ‘age’: 0, ‘job’: ‘Tester’}, {‘name’: ‘James’, ‘age’: 30}]
5、基本类型: yaml中有以下基本类型:
讯享网字符串 整型 浮点型 布尔型 null 时间 日期
我们写个例子来看下:
# 这个例子输出一个字典,其中value包括所有基本类型 str: “Hello World!” int: 110 float: 3.141 boolean: true # or false None: null # 也可以用 ~ 号来表示 null time: 2016-09-22t11:43:30.20+08:00 # ISO8601,写法百度 date: 2016-09-22 # 同样ISO8601
输出:
讯享网{‘str’: ‘Hello World!’, ‘int’: 110, ‘float’: 3.141, ‘boolean’: True, ‘None’: None, ‘time’: datetime.datetime(2016, 9, 22, 3, 43, 30, ), ‘date’: datetime.date(2016, 9, 22)}
如果字符串没有空格或特殊字符,不需要加引号,但如果其中有空格或特殊字符,则需要加引号了
str: 灰蓝 str1: “Hello World” str2: “Hello\nWorld”
输出:
讯享网{‘str’: ‘灰蓝’, ‘str1’: ‘Hello World’, ‘str2’: ‘Hello\nWorld’}
这里要注意单引号和双引号的区别,单引号中的特殊字符转到Python会被转义,也就是到最后是原样输出了,双引号不会被Python转义,到最后是输出了特殊字符;如:
str1: ‘Hello\nWorld’ str2: “Hello\nWorld”
输出:
讯享网{‘str1’: ‘Hello\nWorld’, ‘str2’: ‘Hello\nWorld’}
可以看到,单引号中的’\n’最后是输出了,双引号中的’\n’最后是转义成了回车 6、引用 & 和 * 用于引用
name: &name 灰蓝 tester: *name
这个相当于一下脚本:

讯享网name: 灰蓝 tester: 灰蓝
输出:
{‘name’: ‘灰蓝’, ‘tester’: ‘灰蓝’}
7、强制转换 yaml是可以进行强制转换的,用 !! 实现,如下:
讯享网str: !!str 3.14 int: !!int “123”
输出:
{‘int’: 123, ‘str’: ‘3.14’}
明显能够看出123被强转成了int类型,而float型的3.14则被强转成了str型。
8、分段 在同一个yaml文件中,可以用 — 来分段,这样可以将多个文档写在一个文件中
讯享网— name: James age: 20 — name: Lily age: 19
1、yaml.YAMLObject
yaml.YAMLObject用元类来注册一个构造器(也就是代码里的 init() 方法),让你把yaml节点转为Python对象实例,用表示器(也就是代码里的 repr() 函数)来让你把Python对象转为yaml节点,看代码:
import yaml class Person(yaml.YAMLObject):
讯享网<span class="n">yaml_tag</span> <span class="o">=</span> <span class="s1">'!person'</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o">=</span> <span class="n">age</span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s1">'</span><span class="si">%s</span><span class="s1">(name=</span><span class="si">%s</span><span class="s1">, age=</span><span class="si">%d</span><span class="s1">)'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span><span class="p">)</span>
james = Person(‘James’, 20)
print (yaml.dump(james)) # Python对象实例转为yaml
lily = yaml.load(‘!person {name: Lily, age: 19}’)
print (lily) # yaml转为Python对象实例
输出:
!person {age: 20, name: James}
Person(name=Lily, age=19)
2、yaml.add_constructor 和 yaml.add_representer 你可能在使用过程中并不想通过上面这种元类的方式,而是想定义正常的类,那么,可以用这两种方法
讯享网import yaml
class Person(object):
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span> <span class="o">=</span> <span class="n">age</span> <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">return</span> <span class="s1">'Person(</span><span class="si">%s</span><span class="s1">, </span><span class="si">%s</span><span class="s1">)'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">age</span><span class="p">)</span>
james = Person(‘James’, 20) print (yaml.dump(james)) # 没加表示器之前
def person_repr(dumper, data):
讯享网<span class="k">return</span> <span class="n">dumper</span><span class="o">.</span><span class="n">represent_mapping</span><span class="p">(</span><span class="sa">u</span><span class="s1">'!person'</span><span class="p">,</span> <span class="p">{</span><span class="s2">"name"</span><span class="p">:</span> <span class="n">data</span><span class="o">.</span><span class="n">name</span><span class="p">,</span> <span class="s2">"age"</span><span class="p">:</span> <span class="n">data</span><span class="o">.</span><span class="n">age</span><span class="p">})</span> <span class="c1"># mapping表示器,用于dict</span>
yaml.add_representer(Person, person_repr) # 用add_representer方法为对象添加表示器 print (yaml.dump(james)) # 加了表示器之后
def person_cons(loader, node):
<span class="n">value</span> <span class="o">=</span> <span class="n">loader</span><span class="o">.</span><span class="n">construct_mapping</span><span class="p">(</span><span class="n">node</span><span class="p">)</span> <span class="c1"># mapping构造器,用于dict</span> <span class="n">name</span> <span class="o">=</span> <span class="n">value</span><span class="p">[</span><span class="s1">'name'</span><span class="p">]</span> <span class="n">age</span> <span class="o">=</span> <span class="n">value</span><span class="p">[</span><span class="s1">'age'</span><span class="p">]</span> <span class="k">return</span> <span class="n">Person</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">)</span>
yaml.add_constructor(u‘!person’, person_cons) # 用add_constructor方法为指定yaml标签添加构造器 lily = yaml.load(‘!person {name: Lily, age: 19}’) print (lily)
输出:
讯享网!!python/object:main.Person {age: 20, name: James}
!person {age: 20, name: James}
Person(Lily, 19)
第一行是没加表示器之前,多丑!中间那行是加了表示器之后,变成了规范的格式,下面添加了构造器,能够把 !person 标签转化为Person对象。
四、示例
yaml是一种很清晰、简洁的格式,而且跟Python非常合拍,非常容易操作,我们在搭建自动化测试框架的时候,可以采用yaml作为配置文件,或者用例文件,下面给出一个用例的示例
# Test using included Django test app # First install python-django # Then launch the app in another terminal by doing # cd testapp # python manage.py testserver test_data.json # Once launched, tests can be executed via: # python resttest.py http://localhost:8000 miniapp-test.yaml — - config:
讯享网<span class="o">-</span> <span class="n">testset</span><span class="p">:</span> <span class="s2">"Tests using test app"</span>
- test: # create entity
<span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="s2">"Basic get"</span> <span class="o">-</span> <span class="n">url</span><span class="p">:</span> <span class="s2">"/api/person/"</span>
- test: # create entity
讯享网<span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="s2">"Get single person"</span> <span class="o">-</span> <span class="n">url</span><span class="p">:</span> <span class="s2">"/api/person/1/"</span>
- test: # create entity
<span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="s2">"Get single person"</span> <span class="o">-</span> <span class="n">url</span><span class="p">:</span> <span class="s2">"/api/person/1/"</span> <span class="o">-</span> <span class="n">method</span><span class="p">:</span> <span class="s1">'DELETE'</span>
- test: # create entity by PUT
讯享网<span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="s2">"Create/update person"</span> <span class="o">-</span> <span class="n">url</span><span class="p">:</span> <span class="s2">"/api/person/1/"</span> <span class="o">-</span> <span class="n">method</span><span class="p">:</span> <span class="s2">"PUT"</span> <span class="o">-</span> <span class="n">body</span><span class="p">:</span> <span class="s1">'{"first_name": "Gaius","id": 1,"last_name": "Baltar","login": "gbaltar"}'</span> <span class="o">-</span> <span class="n">headers</span><span class="p">:</span> <span class="p">{</span><span class="s1">'Content-Type'</span><span class="p">:</span> <span class="s1">'application/json'</span><span class="p">}</span>
- test: # create entity by POST
<span class="o">-</span> <span class="n">name</span><span class="p">:</span> <span class="s2">"Create person"</span> <span class="o">-</span> <span class="n">url</span><span class="p">:</span> <span class="s2">"/api/person/"</span> <span class="o">-</span> <span class="n">method</span><span class="p">:</span> <span class="s2">"POST"</span> <span class="o">-</span> <span class="n">body</span><span class="p">:</span> <span class="s1">'{"first_name": "Willim","last_name": "Adama","login": "theadmiral"}'</span> <span class="o">-</span> <span class="n">headers</span><span class="p">:</span> <span class="p">{</span><span class="n">Content</span><span class="o">-</span><span class="n">Type</span><span class="p">:</span> <span class="n">application</span><span class="o">/</span><span class="n">json</span><span class="p">}</span></code></pre></div><p></p>
最近在使用 github+hexo 配置属于自己的博客时遇到了以 yml 为后缀的配置文件,因为不太了解,所以顺便学习一下。
YAML 是一种可读性高,以数据为中心的数据序列化格式。可以表达 对象(键值对),数组,标量 这几种数据形式 能够被多种编程语言和脚本语言解析。
什么是 序列化?
序列化指的是将 自定义的对象或者其他数据进行 持久化,从而 方便进行 传输和存储。一般情况下,能够序列化的数据一定能够通过反序列化恢复。
- 以
k: v的形式来表示键值对的关系,冒号后面必须有一个空格 #表示注释- 对大小写敏感
- 通过缩进来表示层级关系,缩排中空格的数目不重要,只要相同阶层的元素左侧对齐就可以了
- 缩进只能使用空格,不能使用
tab缩进键 - 字符串可以不用双引号
对象和键值对
通过 k: v 的方式表示对象或者键值对,冒号后必须要加一个空格:
讯享网Name: Astron Sex: female School: TJU
通过缩进来表示对象的多个属性:
People: Name: Astron Sex: female School: TJU
也可以写成
讯享网people: {name: Astron, sex: female}
数组
数组(或者列表)中的元素采用 - 表示,以 - 开头的行表示构成一个数组
eg1:
- A - B - C
eg2:
讯享网people: - yyy - zzz - www
行内表示:
people: [yyy, zzz, www]
eg3: 对象数组
讯享网people: - name: yyy age: 18 - name: zzz age: 19
使用流式表示:
people: [{name: yyy, age: 18},{name: zzz, age: 19}]
标量
标量是最基本的不可再分的值,包括:
- 整数
- 浮点数
- 字符串
- 布尔值
- Null
- 时间
- 日期
eg:
讯享网boolean: - true # 大小写都可以 - false float: - 3.14 - 3.25e+5 # 科学计数法 int: 12 null: nodeName: name string: 123 date: 2020-01-01 # 格式为 yyyy-MM-dd datetime: 2020-01-10T15:02:08+08:00 # 日期和时间使用T连接,+表示时区
引用
& 用于建立锚点,* 用于引用锚点,<< 表示合并到当前数据
eg1:
defaults: &defaults adapter: ppp host: q development: database: mq <<: *defaults
相当于:
讯享网defaults: adapter: ppp host: q development: database: mq adapter: ppp host: q
eg2:
- &showell steve - clark - eve - *showell
相当于:
讯享网- steve - clark - eve - steve
脚本语言
YAML 实现简单,解析成本低,所以特别适合在脚本语言中使用
序列化
配置文件
写 YAML 比 XML 方便,所以 YAML 也可以用来做配置文件,但是,不同语言间的数据流转不建议使用YAML。
百度百科 菜鸟教程
PS: 欢迎关注我的私人博客, 以及我的公众号【一起学数据结构与算法】,和我一起成长~!
Yaml是一种可读性高的数据标记语言,Yaml文件是一种配置文件,一般主要用于存储全局配置信息等,可存放不同类型的数据,如列表,字典等。
- 文件后缀.yml
- 大小写敏感
- 空格缩进区分层级,且空格数量不要求,对齐即可
- 表示注释
备注:详细用法见数据类型小节例子
- 数组:序列/列表,按次序排序的值
- 对象:映射/字典/哈希,键值对
- 标量:单个值,不可再分,如字符串,布尔值,Null等
备注:
- 冒号和‘-’后的值前面需空一个空格
- 字符串不使用引号
- 单引号转义特殊字符、空格等
数组
序列/列表,按次序排序的值
# 数组:如列表numbers:[1,2,3,4,5]
- 列表值,使用“-”表示列表中的元素
表示方式1:
numbers:
- 1
- 2
- 3
- 4
- 5
#表示方式2: numbers: [1,2,3,4,5]
对象
映射/字典/哈希,键值对
讯享网# 对象:如字典:ab:{“a”:1,“b”:“哈哈”}
表示方式1
ab: a: 1 b: 哈哈 # 字符串哈哈可不使用引号
表示方式2:
ab: {“a”:1,“b”:“哈哈”}
标量
单个值,不可再分,如字符串,布尔值,Null,日期等
# 标量
字符串
name:susy
布尔值
isFlag: True
Null:使用~表示
a: ~
日期:YYYY-MM-DD格式
d: 2023-03-06
时间:YYYY-MM-DDThh:mm:ss+时区
t: 2018-02-17T15:02:31+08:00
特殊字符、空格
使用单引号转义
email: ‘’ talk: ‘Hello World’
复合结构
包含数组,对象,标量等结构
讯享网# 复合结构:{“code”:200,students:[{name:“张三”,age:12,hobby:[“打篮球”,“跑步”]},{name:“李四”,age:17,hobby:[“打羽毛球”,“看书”]}]}
hobby也可以使用行内写法:
hobby:[打篮球,跑步]
code: 200 students:
- name: 张三 age: 12 hobby: - 打篮球 - 跑步 - name: 李四 age: 17 hobby: - 打羽毛球 - 看书</code></pre></div><p data-pid="UTGkcgky">引用已有键的值,可使用&锚点和*别名来引用,可通俗理解为复制粘贴,可复用yaml文件中已有键值对。</p><div class="highlight"><pre><code class="language-text"># 键值
使用&别名建立锚点,将students全部内容设别名为“stu”
students: &stu name: zhangsan age: 12
引用键
引用students的内容,使用<< *别名即可,<< 表示合并当前数据
class1: <<: *stu
以上内容被读取后输出为:
讯享网# 键值 students:&stu name: zhangsan age: 12
引用键
class1: name: zhangsan age: 12
使用两个感叹号!!可强制转换数据类型。
语法:
key: !!类型名 value
举例:
讯享网# 强制将数据类型1转换成字符类型 number: !!str 1
yaml若包含多个文档,则使用三条横杆“—-”分隔符分隔
—
文件1
a: 1
文件2
b: 2
换行主要使用 | 和 > ,|保留行尾换行符,>将行尾换行符替换成空格。
保留字符末尾的换行使用+,删除字符末尾的换行使用-,一般用于与|和>组合使用。
备注:下面的输出是指读取yaml文件后输出的数据格式,可使用后面python读取yaml文件尝试下
|保留行尾换行符,yaml文件输入:
讯享网w: | Hello World
输出:
{‘w’: ‘Hello\nWorld\n’}
将换行符替换成空,yaml文件输入:
讯享网w: > Hello World
输出:
{‘w’: ‘Hello World\n’}
组合使用
|与+和-的组合使用情况
|+:保留行尾及字符末尾的换行符,yaml文件输入:
讯享网w: |+ Hello World
输出:
{‘w’: ‘Hello\nWorld\n’}
|-:保留行尾换行符,但不保留字符末尾的换行符,yaml文件输入:
讯享网w: |- Hello World
输出:
{‘w’: ‘Hello\nWorld’}
与+和-的组合使用情况
>+:将行尾换行符替换成空格,保留字符末尾的换行符,yaml文件输入:
讯享网w: >+ Hello World
输出:
{‘w’: ‘Hello World\n’}
>-:将行尾换行符替换成空格,不保留字符末尾的换行符,yaml文件输入:
讯享网w: >- Hello World
输出:
{‘w’: ‘Hello World’}
使用?及:实现多值映射,适用于多个变量存在值相同的情况,如变量1和变量2均存在值1和值2。
讯享网变量1: [值1,值2] 变量2: [值1,值2]
使用以下语法表示:
?
- 变量1
- 变量2 :
- 值1
- 值2
举例:
讯享网
# number1: [1,2,3]number2: [1,2,3]
?
- number1
- number2
-
- 1
- 2
- 3
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/202782.html