Yaml 语法简介、PyYAML演示以及网上资源汇总

1. YAML 是什么意思

YAML 是 “YAML Ain’t a Markup Language” 的递归缩写。不过,在正式发布之前的开发过程中,内部人员则称 YAML 为 “Yet Another Markup Language“。

“YAML Ain’t a Markup Language” 中的 Markup Language 主要指 XML,这句话也体现出 YAML 想要追求的与XML不同的目标(Goals of YAML):

  1. YAML is easily readable by humans.
  2. YAML data is portable between programming languages.
  3. YAML matches the native data structures of agile languages.
  4. YAML has a consistent model to support generic tools.
  5. YAML supports one-pass processing.
  6. YAML is expressive and extensible.
  7. YAML is easy to implement and use.

2. 语法简介

  • YAML 的配置文件后缀为 .yml,如:runoob.yml 。
  • 大小写敏感
  • 使用缩进表示层级关系
  • 缩进不允许使用tab,只允许空格
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可
  • ‘#’表示注释,从这个字符一直到行尾,都会被解析器忽略

YAML 继承并集成了很多语言的精髓:

  • 上述缩进表示层级关系的方式与 Python 类似
  • YAML 也允许使用指示符(如[])表示层级关系,这又与 Perl 类似
  • 双引号形式中的转义符,则类似 C 的风格

YAML 直接支持集合(collection)与纯量(scalar)类型。而集合类型则包括映射(mapping)与顺序(sequence)两种。

不过中文互联网把后两种类型翻译为对象和数组,个人感觉不是很妥当。

下面对这三种数据类型一一进行介绍。

2.1 映射(mapping,中文常见译法:对象)

映射与 Python 中的字典(dict)类型类似。

YAML 用 key: value 来表示一个映射。注意,冒号后面需要有一个空格。

2.1.1 PyYAML —— Python 的主力 YAML 库

Python idle 能即时检验命令执行结果,很是方便;所以下面我们其来进行相关演示。

Python 自带的 YAML 库为 PyYAML,使用相当简单:

  • import yaml 命令加载 PyYAML 库;
  • yaml.load 命令将 YAML 流加载为 Python 数据;
  • yaml.dump 命令将 Python 数据导出为 YAML 流

注意,对于不信任的字符流直接使用 yaml.load 有可能存在安全隐患,因此我们用官方推荐的更安全的 yaml.safe_load 来代替 yaml.load(PyYAML 对 yaml.load 风险的官方解释)。

在 Python idle 中执行如下代码,得到的结果是 {'a': 'b'}。

1
2
3
import yaml
str = "a: b"
yaml.safe_load(str)

继续执行以下代码,得到的结果是 'name: Tao\n'。

1
2
3
d = dict()
d["name"]="Tao"
yaml.dump(d)

注:后续示例中省略 import yaml 语句。

2.2 顺序(sequence,中文常见译法:数组)

顺序与 Python 中的列表(list)类型类似。

YAML 用一组连字符开头的行来表示一个顺序(这有点像 markdown 语法)。注意,连字符后面需要有一个空格。

1
2
- foo
- bar

在 Python idle 中执行如下代码,得到的结果是 ['foo', 'bar']。

1
2
3
4
str = '''
- foo
- bar'''
yaml.safe_load(str)

2.2.1 复合结构

YAML 支持映射与顺序的多层嵌套,以形成复合结构。

在 Python idle 中执行如下代码,得到的结果是 Tom & Jerry。

1
2
3
4
5
6
7
8
9
str = '''
- #0
name: Tom
type: cat
- #1
name: Jerry
type: mouse'''
l = yaml.safe_load(str)
print(l[0]["name"] + " & " + l[1]["name"])

2.3 纯量(scalar)

纯量是单个的、不可再分的值。

YAML 中的纯量有以下几种:

2.3.1 字符串

字符串默认不使用引号表示,如:这是一个字符串,Hello World 都是字符串。

在 Python idle 中执行如下代码,得到的结果是 Hello World。

1
2
d = yaml.safe_load("a: Hello World")
d["a"]

在上述例子中,YAML 解释器能够理解 Hello World 是一个字符串,所以我们无需用引号。但当某些情况下,就需要引号来帮助解释器识别字符串了;比如说,字符串中有特殊符号:b: 'Hello: World'。

另外 YAML 还支持多行字符串。

在 Python idle 中执行如下代码,得到的结果是 'Hello\nWorld\n'。

1
2
3
4
5
6
7
str = '''
a: |
Hello
World
'''
d = yaml.safe_load(str)
d["a"]

2.3.2 布尔值

YAML 用 true 与 false 表示。

在 Python idle 中执行如下代码,得到的结果是 [True, False]。注意 true 变为 True,这意味着是布尔值”真”,而非字符串。

1
2
3
4
5
str = '''
a: true
b: false'''
d = yaml.safe_load(str)
list(d.values())

2.3.3 数值

YAML 中的数值直接以字面量的形式表示即可。

在 Python idle 中执行如下代码,得到的结果是 5.140000000000001。

1
2
3
4
5
str = '''
a: 2
b: 3.14'''
d = yaml.safe_load(str)
d["a"]+d["b"]

2.3.4 Null

YAML 用 ~ 表示 Null。

在 Python idle 中执行如下代码,得到的结果是 True。

1
2
3
str = "a: ~"
d = yaml.safe_load(str)
d["a"] is None

2.3.5 日期与时间

YAML 中的日期、时间使用ISO 8601格式:

  • 日期为:yyyy-MM-dd;
  • 时间为:yyyy-MM-ddThh:mm:ss+hh:mm,T 后面跟着的是时间,+ 或 - 后面跟着的是时区(偏移)。

在 Python idle 中执行如下代码,得到的结果是 [datetime.date(2020, 2, 15), datetime.datetime(2020, 2, 15, 13, 30, tzinfo=datetime.timezone(datetime.timedelta(-1, 57600)))]。

1
2
3
4
5
str = '''
a: 2020-02-15
b: 2020-02-15T13:30:00-08:00'''
d = yaml.safe_load(str)
list(d.values())

介绍到这里,对于一般使用来说应该足够了;说那么复杂的,十年八年用不上,也记不住。如果遇到更复杂的情况,我们直接上网找 References 就好了。

3. 网络资源

另外,这个 IBM Developer - YAML 简介 给出了一个复合结构的例子:

1
2
3
4
5
6
7
8
9
10
name: John Smith
age: 37
spouse:
name: Jane Smith
age: 25
children:
- name: Jimmy Smith
age: 15
- name: Jenny Smith
age: 12

如果深入研究的话还可能发现一些社会问题。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器