前言
今天来填前文留下的坑,要说的就是最后一种常用的配置文件格式—— YAML。
YAML 是 “YAML Ain’t a Markup Language”(YAML 不是一种标记语言)的递归缩写。
YAML是为了替代 XML(Extensible Markup Language 可扩展标记语言) 而生,它在 Ruby 中被发扬光大并为世人所知。
如今在很多地方都能看到YAML配置文件的身影,例如面向YAML编程的K8S工程师(笑)。
特点
YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)。
YAML 的配置文件后缀为 .yml,如:yumefx.yml 。
相比XML,YAML有XML的下列优点:
- YAML可以基于流来处理;
- YAML表达能力强,扩展性好。
另外,YAML又有XML不具备的优点:
- YAML的可读性好。
- YAML和脚本语言的交互性好。
- YAML使用实现语言的数据类型。
- YAML有一个一致的信息模型。
- YAML易于实现。
总之,YAML试图用一种比XML更敏捷的方式,来完成XML所完成的任务。
YAML 完全达到前文提到的优秀配置文件的标准,堪称完美。
另外,YAML需要注意以下几条:
- 大小写敏感
- 使用缩进表示层级关系,缩进不允许使用tab,只允许空格
- 缩进的空格数不重要,只要相同层级的元素左对齐即可
- ‘#’表示注释
数据类型
YAML有以下三种数据类型:
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
- 纯量(scalars):单个的、不可再分的值
YAML对象
对象键值对使用冒号结构表示 key:
value,冒号后面要加一个空格。
可以使用 key:{key1: value1, key2: value2, …}进行对象的嵌套。
还可以使用缩进表示层级关系;
key: child-key: value child-key2: value2
对于复杂的对象格式,可以使用?
(问号+空格)代表key,配合:
(冒号+空格)代表对应的value,例如:
? - complexkey1 - complexkey2 : - complexvalue1 - complexvalue2
意思是对象的属性是一个数组 [complexkey1,complexkey2],对应的值也是一个数组 [complexvalue1,complexvalue2]。
YAML 数组
以 – 开头的行表示构成一个数组:
- A - B - C
多维数组,可以使用行内表示:
key: [value1, value2, ...]
数组嵌套方式如下:
- - A - B - C
一个复杂的复合结构如下:
companies: - id: 1 name: company1 price: 200W - id: 2 name: company2 price: 500W languages: - Ruby - Perl - Python websites: YAML: yaml.org Ruby: ruby-lang.org Python: python.org Perl: use.perl.org
以流式方式表示:
{companies:[{id: 1,name: company1,price: 200W},{id: 2,name: company2,price: 500W}],languages:[Ruby,Perl,Python],websites:{YAML: yaml.org,Ruby: ruby-lang.org,Python: python.org,Perl: use.perl.org}}
转换为JSON则为:
{ "companies":[ { "id":1, "name":"company1", "price":"200W" }, { "id":2, "name":"company2", "price":"500W" } ], "languages":[ "Ruby", "Perl", "Python" ], "websites":{ "YAML":"yaml.org", "Ruby":"ruby-lang.org", "Python":"python.org", "Perl":"use.perl.org" } }
纯量
纯量是最基本的,不可再分的值,包括:
- 字符串
- 布尔值
- 整数
- 浮点数
- Null
- 时间
- 日期
使用一个例子来快速了解纯量的基本使用:
boolean: - TRUE #true,True都可以 - FALSE #false,False都可以 float: - 3.14 - 6.8523015e+5 #可以使用科学计数法 int: - 123 - 0b1010_0111_0100_1010_1110 #二进制表示 null: nodeName: 'node' parent: ~ #或者null string: - 哈哈 - 'Hello world' #可以使用双引号或者单引号包裹特殊字符 - newline newline2 #字符串可以拆成多行,每一换行会被转化成一个空格 date: - 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd datetime: - 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
yaml也可以对纯量进行强制转换。
str: !!str 3.14 int: !!int "123"
其他格式
引用
引用是导入之前定义的数据到此行,避免同样数据的重复书写和重复修改。
&
用来建立锚点(defaults),<<
表示合并到当前数据,*
用来引用锚点。
例如下面的简单例子:
- &showell Steve - Clark - Brian - Oren - *showell
相当于
- Steve - Clark - Brian - Oren - Steve
复合结构也可以引用。
defaults: &defaults adapter: postgres host: localhost development: database: myapp_development <<: *defaults test: database: myapp_test <<: *defaults
相当于
defaults: adapter: postgres host: localhost development: database: myapp_development adapter: postgres host: localhost test: database: myapp_test adapter: postgres host: localhost
多块YAML
一个yaml文件里可以存在多块文件内容,通过—进行分隔,只能一起读取。
--- user: admin pwd: admin job: - teacher - nurese --- school: erxiao location: sky
Python读写YAML
Python可以使用PyYaml库读写YAML,安装方式如下:
pip install PyYaml
一个简单的读写YAML代码示例
import yaml def readYAML(): with open("settings.yml","r",encoding="utf-8") as ymlFile: cont = ymlFile.read() settings = yaml.load(cont, Loader=yaml.FullLoader) keys = settings.keys() items = settings.items() print(settings["companies"][1]) # 多块yaml使用迭代器读取 def readYAMLAll(): with open("settings.yml","r",encoding="utf-8") as ymlFile: cont = ymlFile.read() settings = yaml.load_all(cont, Loader=yaml.FullLoader) for data in settings: print(data) def writeYAML(): with open("settings.yml","w",encoding="utf-8") as ymlFile: data = { "companies":[ { "id":1, "name":"company1", "price":"200W" }, { "id":2, "name":"company2", "price":"500W" } ] } yaml.dump(data,ymlFile) # 多块yaml输出 def writeYAMLAll(): with open("settings.yml","w",encoding="utf-8") as ymlFile: data = { "companies":[ { "id":1, "name":"company1", "price":"200W" }, { "id":2, "name":"company2", "price":"500W" } ] } yaml.dump_all([data,data,data],ymlFile)
注意
单引号或者双引号包裹字符串时Python读取时是有差别的,单引号包裹时,字符串里的特殊字符会被自动转义,原样输出;而双引号包裹时,特殊字符不转义,直接输出特殊字符。
'Hello\nWorld' # Hello\nWorld "Hello\nWorld" #Hello #World
本文转载自菜鸟教程,有修改。
年岁渐长,自信心也逐渐增加,
原来巨石也不外一粒沙。
——梁文道
评论
还没有任何评论,你来说两句吧!