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.loadPyYAML 对 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 用 truefalse 表示。

在 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:mmT 后面跟着的是时间,+- 后面跟着的是时区(偏移)。

在 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等现代浏览器