yaml基本语法
yaml在python的使用
pyyaml

yaml概述


YAML(YAML Ain't Markup Language)是一种标记语言(Yet Another Markup Language),是一种较为人性化的数据序列化语言,可以配合目前大多数编程语言使用。
YAML 的语法比较简洁直观,特点是使用空格来表达层次结构,其最大优势在于数据结构方面的表达,所以 YAML 更多应用于编写配置文件,且比JSON 格式更加简洁方便。

yaml官方文档

yaml 官网
yaml 1.2官方文档

yaml基本语法


yaml编写规则

  1. 使用#注释
  2. 区分大小写
  3. 大小写敏感
  4. 使用缩进表示层级关系
  5. 缩进格式:使用空格缩进,非TAB键。空格数目不固定,相同层级一致即可
# 这是yaml注释
one:
  One: 1 # 大小写敏感
  three:
    four: 4
    five: 5 # 相同层级缩进一致

等效json:

{
    "one":{
        "One":1,
        "three":{
            "four":4,
            "five":5
        }
    }
}

显然YAML要简洁很多,不需要大括号、不需要引号

接下来介绍yaml常见数据类型,由于对json比较熟悉,接下来通过将常用json字符串转换成yaml

数组

一组按次序排列的值,又称为序列(sequence) / 列表(list)

  1. 一维数组
    ["jerry", 28, "shanghai"]
    
    对应的yaml为:
    - jerry
    - 28
    - shanghai
    
  2. 多维数组
    [ [ "jerry", 28, "shanghai" ], [ "tom", 26, "beijing" ] ]
    
    对应的yaml为:
    -
    - jerry
    - 28
    - shanghai
    -
    - tom
    - 26
    - beijing
    

注:-后必须有空格

对象

键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)

  1. key: value
    { "name": "jerry", "age": 28, "address": "shanghai" }
    
    对应的yaml为:
    name: jerry
    age: 28
    address: shanghai
    
  2. 多层嵌套
    { "name": "jerry", "age": 28, "address": "shanghai", "friend": { "boyfriend": "tom", "girlfriend": "lily" } }
    
    对应的yaml为:
    name: jerry
    age: 28
    address: shanghai
    friend:
      boyfriend: tom
      girlfriend: lily
    

注:-后必须有空格

数组与对象组合

  1. 对象嵌套数组
    {"name": "jerry", "age": 28, "language":["java","golang","python"], "other_info": ["address": "shanghai", "boyfriend": "tom"]}
    
    对应yaml为:
    name: jerry
    age: 28
    language:
      - java
      - golang
      - python
    other_info:
      - address: shanghai
      - boyfriend: tom
    
  2. 数组嵌套对象
    [{"name": "jerry"}, {"age": 28}, {"address": "shanghai", "girlfriend": "lily"}, {"salary": 99999, "pet": "bingo"}]
    
    对应的yaml为:
    - name: jerry
    - age: 28
    - address: shanghai
       girlfriend: lily
    - salary: 99999
       pet: bingo
    

纯量

纯量(scalars) : 单个的、不可再分的值
字符串、整数、浮点数、Null、布尔值、时间、日期

  1. 字符串
    字符串一般不需要用引号包裹,但是如果字符串中使用了反斜杠“\”开头的转义字符就必须使用引号包裹
    info:
      - monkey jerry # 不用引号包裹
      - monkey
       jerry # 拆成多行后会自动在中间添加空格
      - 'monkey jerry' # 单引号包裹
      - "welcome to jerry's blog" # 双引号包裹
      - 'I said: "hello, monkey jerry"' # 单双引号支持嵌套
      - "monkey jerry. \u263A" # 使用双引号包裹时支持 Unicode 编码
      - "\x0d\x0a is \r\n" # 使用双引号包裹时还支持 Hex 编码
    
  2. 整数和浮点数
    {"age": 28, "salary": 99999.9}
    
    对应的yaml为:
    age: 28
    salary: 99999.9
    
  3. { "nulls": [null, null, null, null] }
    
    对应的yaml
    nulls:
      - null
      - Null
      - ~
      - 
    

    “null”、“Null”和“~”都是空,不指定值默认也是空

  4. 布尔值
    { "boolean": [true, true, false, false] }
    
    对应的yaml为:
    boolean:
      - true # True、TRUE
      - yes # Yes、YES
      - false # False、FALSE
      - no # No、NO
    
    1. “true”、“True”、“TRUE”、“yes”、“Yes”和“YES”皆为真
    2. “false”、“False”、“FALSE”、“no”、“No”和“NO”皆为假
  5. 时间和日期
    time: 2019-09-03t01:00:05
    date: 2019-09-03
    

数据重用和合并

  1. 建立锚点&和引用锚点*
    为了保持内容的简洁,避免过多重复的定义,YAML 提供了由锚点标签“&”和引用标签“*”组成的语法来快速引用相同的数据
    { "jerry": {"age": 28, "address": "shanghai"}, "tom": {"age": 28, "address": "shanghai"}}
    
    对应的yaml可表示为:
    jerry: &info # &设置锚点
      age: 28
      address: shanghai
    tom: *info # *引用锚点
    
  2. 合并<<
    配合合并标签“<<”使用可以与任意数据进行合并,你可以把这套操作想象成面向对象语言中的继承
    { "jerry": {"age": 28, "address": "shanghai"}, "tom": {"age": 28, "address": "shanghai", "skill": "python"}, "lily": {"age": 28, "address": "beijing", "skill": "golang"}}
    
    对应的yaml可表示为:
    jerry: &info # 设置锚点
      age: 28
      address: shanghai
    tom:
      <<: *info # 引用锚点,实例化时会自动展开
      skill: python # 添加额外的属性
    lily:
      <<: *info # 引用锚点
      address: beijing # 覆盖锚点中的属性
      skill: golang
    

yaml在python的使用


pyyaml

  1. 安装
pip install pyyaml
  1. 官方文档
    pyyaml 官方文档

在python中使用

更多关于pyyaml在python中的特性请参看以上官方文档,这里仅介绍个人常用
如下data.yaml文件(可理解为配置文件):

info:
  basic_info:
    name: jerry
    age: 28
  other_info:
    address: shanghai
    salary: 99999
  1. 使用yaml.safe_load获取jerry的工资:
    import yaml
    with open("data.yaml") as f:
        yaml_data = f.read()
        info = yaml.safe_load(yaml_data)
    print(type(info))
    print(info)
    jerry_salary = info['info']['other_info']['salary']
    print(jerry_salary)
    -----------------------------------------
    <class 'dict'>
    {'info': {'basic_info': {'name': 'jerry', 'age': 28}, 'other_info': {'address': 'shanghai', 'salary': 99999}}}
    99999
    
  2. 修改jerry的地点为beijing后并存入新的yaml文件(yaml.safe_dump):
    import yaml
    with open("data.yaml") as f:
        yaml_data = f.read()
        info = yaml.safe_load(yaml_data)
    
    info['info']['other_info']['address'] = 'beijing'
    with open("new_data.yaml", "w") as f:
        f.write(yaml.dump(info))
    
  3. 使用yaml处理json
    YAML是JSON的超集,所以解析YAML的程序也能正常解析JSON格式
    data.yaml数据对应的data.json可表示为:
    {"info":{"basic_info":{"name":"jerry","age":28},"other_info":{"address":"shanghai","salary":99999}}}
    
    用1中的程序处理:
    import yaml
    with open("data.json") as f:
        yaml_data = f.read()
        info = yaml.safe_load(yaml_data)
    print(type(info))
    print(info)
    jerry_salary = info['info']['other_info']['salary']
    print(jerry_salary)
    

    运行以上程序,可以看出实现了相同的效果

相关链接


参考