PyYaml简单学习

YAML是一种轻型的配置文件的语言,远比JSON格式方便,方便人类读写,它通过缩进来表示结构,很具有Python风格。
安装:pip insall pyyaml

YAML语法

  • 文档

YAML数据流是0个或者多个文档,文档之间用---分割,文档可选用...结束,单个文档可用也可不用---开头。

隐式文档如下:

"""
- Multimedia
- Internet
- Education
"""
'\n- Multimedia\n- Internet\n- Education\n'

显式文档如下:

"""
---
- Multimedia
- Internet
- Education
...
"""
'\n---\n- Multimedia\n- Internet\n- Education\n...\n'
  • 序列

序列用-空格来表示

yaml.load("""
- The Dagger
- The daager
- The Daaage
""")
['The Dagger', 'The daager', 'The Daaage']

序列可以嵌套:

yaml.load("""
-
    - HTML
    - LaTex
    - XML
    - VRML
    - YAML
-
    - BSD
    - GNU HURD
    - LINUX
""")
[['HTML', 'LaTex', 'XML', 'VRML', 'YAML'], ['BSD', 'GNU HURD', 'LINUX']]

也可不用另起一行来新建嵌套的序列:

yaml.load("""
- 1.1
- - 2.1
  - 2.2
- - - 3.1
    - 3.2
    - 3.3

""")
[1.1, [2.1, 2.2], [[3.1, 3.2, 3.3]]]

序列也可以嵌套到映射中:

yaml.load("""
left hand:
        - Ring of Tesla
        - Ring of King
right hand:
        - Ring of Asia
        - Ring of Cold
""")
{'left hand': ['Ring of Tesla', 'Ring of King'],
 'right hand': ['Ring of Asia', 'Ring of Cold']}
  • 映射

键值对用:空格来表示:

yaml.load("""
base armor: 0
base damaage: [4,4]
plus to: 16
multi:
    - test test
    - tets
""")
{'base armor': 0,
 'base damaage': [4, 4],
 'plus to': 16,
 'multi': ['test test', 'tets']}

复杂的键可以用?空格,比如字典的键如果是tuple类型,而序列是List,众所周知,Python中字典的键只能是不可变的对象,所以需要将List 转换为tuple.

yaml.load("""
? !!python/tuple [0,0] 
: The hero
""")
{(0, 0): 'The hero'}

映射也可以嵌套:

yaml.load("""
hero: 
    hp: 34
    sp: 9
orc:
    hp: 12
    sp: 34
""")
{'hero': {'hp': 34, 'sp': 9}, 'orc': {'hp': 12, 'sp': 34}}

映射也可以嵌套在序列中

yaml.load("""
- name: PyYAML
  status: 4
  langauage: python
- name: PYSYCK
  status: 5
  license: BSD
""")
[{'name': 'PyYAML', 'status': 4, 'langauage': 'python'},
 {'name': 'PYSYCK', 'status': 5, 'license': 'BSD'}]
  • 标量

有5种标量:纯文本,单引号,双一号,字面量,折叠式

yaml.load("""
plain: Scroll of Remove Curse
single-quoted: 'Easy know'
double-quoted: "?"
literal:
     __              /.-.\
    /  )_____________\\  Y
   /_ /=== == === === =\ _\_
  ( /)=== == === === == Y   \
   `-------------------(  o  )
                        \___/
folded: >
 It removed all ordinary curses from all equipped items. # 注意开头的空格
 Heavy or permanent curses are unaffected  

""")
{'plain': 'Scroll of Remove Curse',
 'single-quoted': 'Easy know',
 'double-quoted': '?',
 'literal': '__              /.-.    /  )_____________\\  Y /_ /=== == === === =\\ _\\_ ( /)=== == === === == Y      `-------------------(  o  ) \\___/',
 'folded': 'It removed all ordinary curses from all equipped items. # 注意开头的空格 Heavy or permanent curses are unaffected  \n'}

加载YAML

import yaml

直接用yaml.load来加载一个不可信任的文件是非常不安全的,yaml.loadpickle.load一样强大,都可以调用任何Python函数。可以考虑用yaml.safe_load

yaml.load将一个YAML文档转化为一个Python对象。

需要注意的是 '-' 与字符串之间需要有空格,才表示一个列表。

a=yaml.load("""
 - Hesper
 - Pali
 - Apat
 - Epip
""")
a
['Hesper', 'Pali', 'Apat', 'Epip']
type(a)
list
yaml.load("""
 测试: 中文 
 age: 30
""") 
{'测试': '中文', 'age': 30}

需要重要的是 :与字符串之间也有空格

  • 如果一个字符串或者文件包含多个文档,可以用yaml.load_all函数。
documents="""
---
name: first one
description: dkfsjk
---
name: johnyang
age: 29

---
- C
- C++
- C#
- B #
"""

注意多个文档之间用---分割。

yaml.load_all(documents)
<generator object load_all at 0x0000029B36EC2390>
for data in yaml.load_all(documents):
    print(data)
{'name': 'first one', 'description': 'dkfsjk'}
{'name': 'johnyang', 'age': 29}
['C', 'C++', 'C#', 'B']

空格 '#'是表示注释

  • PyYAML允许构建任意类型的Python对象
yaml.load("""
none: [~,null]
bool: [ture,false,on,off]
int: 42
float: 3.14159
list: [LIST,RES]
dict: {hhp: 13,sps: dkf}
multiDict:
        dksk: fjsdk
        jfksd: eiw
""")
{'none': [None, None],
 'bool': ['ture', False, True, False],
 'int': 42,
 'float': 3.14159,
 'list': ['LIST', 'RES'],
 'dict': {'hhp': 13, 'sps': 'dkf'},
 'multiDict': {'dksk': 'fjsdk', 'jfksd': 'eiw'}}
  • 甚至Python 类实例可以用!!python/object来创建
class Hero:
    def __init__(self,name,hp,sp):
        self.name=name
        self.hp=hp
        self.sp=sp
    def __repr__(self):
        return "%s(name=%r,hp=%r,sp=%r)" %(self.__class__.__name__,self.name,self.hp,self.sp)
yaml.load("""
!!python/object:__main__.Hero  
name: jksdfk
hp: 1200
sp: 0

""")
Hero(name='jksdfk',hp=1200,sp=0)

注意 !!python/object:__main__.Hero中的:后面没有空格!

导出YAML

yaml.dump接受Python对象,导出为一个YAML文档。

print(yaml.dump({'name':'johnyang','age':29,'hobby':['coding','reading','thinking']}))
age: 29
hobby: [coding, reading, thinking]
name: johnyang

yaml.dump接受第二个可选的参数,必须是打开的文本/二进制文件,这种情况下,yaml.dump将会把产生的yaml文档写入该文本,否则yaml.dump返回产生的文档。

stream=open('testYaml.yaml','w')
yaml.dump(data,stream)
print(yaml.dump(data))
{age: 29, name: johnyang}

print(yaml.dump([1,2,3],explicit_start=True))
--- [1, 2, 3]

print(yaml.dump(Hero('Gauss',hp=-3,sp=3)))
!!python/object:__main__.Hero {hp: -3, name: Gauss, sp: 3}

  • yaml.dump支持管控输出格式的可选参数
print(yaml.dump(list(range(50))))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
  23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
  43, 44, 45, 46, 47, 48, 49]

print(yaml.dump(list(range(50)),width=50,indent=4))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
    28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
    40, 41, 42, 43, 44, 45, 46, 47, 48, 49]

print(yaml.dump(list(range(5)),canonical=True)) #canonical 意思是典型的;规范化
---
!!seq [
  !!int "0",
  !!int "1",
  !!int "2",
  !!int "3",
  !!int "4",
]

print(yaml.dump(list(range(5)),default_flow_style=False))
- 0
- 1
- 2
- 3
- 4

print(yaml.dump(list(range(5)),default_flow_style=True))
[0, 1, 2, 3, 4]

print(yaml.dump(list(range(5)),default_flow_style=True,default_style='""'))
[!!int "0", !!int "1", !!int "2", !!int "3", !!int "4"]


posted @ 2020-12-19 12:06  JohnYang819  阅读(415)  评论(0编辑  收藏  举报