PyYAML文档
PyYAML现在维护在https://github.com/yaml/pyyaml。此页面仅用于历史目的。
英文文档链接:http://pyyaml.org/wiki/PyYAMLDocumentation
安装
下载源码包PyYAML-3.12.tar.gz并解压缩。转到目录PyYAML-3.12并运行
$ python setup.py install
如果要使用比纯Python版本快得多的LibYAML绑定,则需要下载并安装LibYAML。然后你可以通过执行来构建和安装绑定
$ python setup.py --with-libyaml install
为了使用基于LibYAML的解析器和发射器,使用类CParser
和CEmitter
。例如,
from yaml import load, dumptry:from yaml import CLoader as Loader, CDumper as Dumperexcept ImportError:from yaml import Loader, Dumper# ...data = load(stream, Loader=Loader)# ...output = dump(data, Dumper=Dumper)
请注意,纯Python和基于LibYAML的解析器和发射器之间存在一些细微差别(但不是真正重要的)差异。
经常问的问题
没有嵌套集合的字典不能正确转储
为什么
import yaml document = """ a: 1 b: c: 3 d: 4"""print yaml.dump(yaml.load(document))
给
a: 1 b: {c: 3, d: 4}
(见#18,#24)?
这是一个正确的输出,尽管嵌套映射的风格是不同的。
默认情况下,PyYAML根据是否有嵌套集合来选择集合的样式。如果一个集合有嵌套的集合,它将被分配块的样式。否则就会有流动风格。
如果你想收藏到块样式总是被序列,设置参数default_flow_style
的dump()
到False
。例如,
>>> print yaml.dump(yaml.load(document), default_flow_style=False) a: 1b: c: 3 d: 4
Python 3的支持
从3.08版本开始,PyYAML和LibYAML绑定为Python 3提供了完整的支持。这是Python 2和Python 3版本之间PyYAML API差异的简要概述。
在Python 2中:
str
对象被转换成!!str
,!!python/str
或!binary
根据对象是否是一个ASCII,UTF-8或二进制字符串节点。unicode
对象根据对象是否是ASCII字符串被转换为!!python/unicode
或!!str
节点。yaml.dump(data)
将该文档生成为UTF-8编码str
对象。yaml.dump(data, encoding=('utf-8'|'utf-16-be'|'utf-16-le'))
str
以指定的编码生成一个对象。yaml.dump(data, encoding=None)
产生一个unicode
对象。
在Python 3中:
str
对象被转换为!!str
节点。bytes
对象被转换为!!binary
节点。由于兼容性的原因,
!!python/str
和!python/unicode
标签仍然支持和相应的节点转换为str
对象。yaml.dump(data)
生成文档作为str
对象。yaml.dump(data, encoding=('utf-8'|'utf-16-be'|'utf-16-le'))
bytes
以指定的编码生成一个对象。
教程
从导入yaml
包开始。
>>> import yaml
加载YAML
警告:yaml.load
从任何不受信任的来源收到任何数据都是不安全的!yaml.load
是一样强大的pickle.load
,所以可以调用任何Python函数。yaml.safe_load
虽然检查功能。
该函数yaml.load
将YAML文档转换为Python对象。
>>> yaml.load("""... - Hesperiidae... - Papilionidae... - Apatelodidae... - Epiplemidae... """) ['Hesperiidae', 'Papilionidae', 'Apatelodidae', 'Epiplemidae']
yaml.load
接受一个字节字符串,一个Unicode字符串,一个打开的二进制文件对象或一个打开的文本文件对象。字节字符串或文件必须使用utf-8,utf-16-be或utf-16-le编码进行编码。yaml.load
通过检查字符串/文件开始处的BOM(字节顺序标记)序列来检测编码。如果不存在BOM,则假定utf-8编码。
yaml.load
返回一个Python对象。
>>> yaml.load(u"""... hello: Привет!... """) # In Python 3, do not use the 'u' prefix{'hello': u'\u041f\u0440\u0438\u0432\u0435\u0442!'}>>> stream = file('document.yaml', 'r') # 'document.yaml' contains a single YAML document.>>> yaml.load(stream) [...] # A Python object corresponding to the document.
如果字符串或文件包含多个文档,则可以使用该yaml.load_all
函数加载它们。
>>> documents = """... ---... name: The Set of Gauntlets 'Pauraegen'... description: >... A set of handgear with sparks that crackle... across its knuckleguards.... ---... name: The Set of Gauntlets 'Paurnen'... description: >... A set of gauntlets that gives off a foul,... acrid odour yet remains untarnished.... ---... name: The Set of Gauntlets 'Paurnimmen'... description: >... A set of handgear, freezing with unnatural cold.... """>>> for data in yaml.load_all(documents): ... print data {'description': 'A set of handgear with sparks that crackle across its knuckleguards.\n','name': "The Set of Gauntlets 'Pauraegen'"} {'description': 'A set of gauntlets that gives off a foul, acrid odour yet remains untarnished.\n','name': "The Set of Gauntlets 'Paurnen'"} {'description': 'A set of handgear, freezing with unnatural cold.\n','name': "The Set of Gauntlets 'Paurnimmen'"}
PyYAML允许你构造任何类型的Python对象。
>>> yaml.load("""... none: [~, null]... bool: [true, false, on, off]... int: 42... float: 3.14159... list: [LITE, RES_ACID, SUS_DEXT]... dict: {hp: 13, sp: 5}... """) {'none': [None, None], 'int': 42, 'float': 3.1415899999999999,'list': ['LITE', 'RES_ACID', 'SUS_DEXT'], 'dict': {'hp': 13, 'sp': 5},'bool': [True, False, True, False]}
即使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: Welthyr Syxgon... hp: 1200... sp: 0... """) Hero(name='Welthyr Syxgon', hp=1200, sp=0)
请注意,如果从不受信任的源(如Internet)接收到YAML文档,则构建任意Python对象的功能可能很危险。该函数yaml.safe_load
将这种功能限制在简单的Python对象(如整数或列表)上。
一个python对象可以被标记为安全的,从而被识别yaml.safe_load
。为此,从yaml.YAMLObject
(如构造函数,表示者,解析器部分中所解释的)中派生它,并明确地将其类属性设置yaml_loader
为yaml.SafeLoader
。
倾销YAML
该yaml.dump
函数接受一个Python对象并产生一个YAML文档。
>>> print yaml.dump({'name': 'Silenthand Olleander', 'race': 'Human', ... 'traits': ['ONE_HAND', 'ONE_EYE']}) name: Silenthand Olleander race: Human traits: [ONE_HAND, ONE_EYE]
yaml.dump
接受第二个可选参数,该参数必须是开放文本或二进制文件。在这种情况下,yaml.dump
将生成的YAML文件写入文件。否则,yaml.dump
返回生成的文件。
>>> stream = file('document.yaml', 'w')>>> yaml.dump(data, stream) # Write a YAML representation of data to 'document.yaml'.>>> print yaml.dump(data) # Output the document to the screen.
如果您需要将多个YAML文档转储到单个流,请使用该功能yaml.dump_all
。yaml.dump_all
接受一个列表或一个生成器
将Python对象序列化成YAML文档。第二个可选参数是一个打开的文件。
>>> print yaml.dump([1,2,3], explicit_start=True)--- [1, 2, 3]>>> print yaml.dump_all([1,2,3], explicit_start=True)--- 1--- 2--- 3
你甚至可以转储Python类的实例。
>>> 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)>>> print yaml.dump(Hero("Galain Ysseleg", hp=-3, sp=2))!!python/object:__main__.Hero {hp: -3, name: Galain Ysseleg, sp: 2}
yaml.dump
支持一些指定发射器格式细节的关键字参数。例如,您可以设置首选的intendation和width,使用规范的YAML格式或强制首选样式作为标量和集合。
>>> print yaml.dump(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(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(range(5), canonical=True)---!!seq [ !!int "0", !!int "1", !!int "2", !!int "3", !!int "4", ]>>> print yaml.dump(range(5), default_flow_style=False)- 0- 1- 2- 3- 4>>> print yaml.dump(range(5), default_flow_style=True, default_style='"') [!!int "0", !!int "1", !!int "2", !!int "3", !!int "4"]
构造者,代表者,解析者
您可以定义您自己的应用程序特定的标签。最简单的方法是定义一个子类yaml.YAMLObject
:
>>> class Monster(yaml.YAMLObject): ... yaml_tag = u'!Monster'... def __init__(self, name, hp, ac, attacks): ... self.name = name ... self.hp = hp ... self.ac = ac ... self.attacks = attacks ... def __repr__(self): ... return "%s(name=%r, hp=%r, ac=%r, attacks=%r)" % ( ... self.__class__.__name__, self.name, self.hp, self.ac, self.attacks)
上面的定义足以自动加载和转储Monster
对象:
>>> yaml.load("""... --- !Monster... name: Cave spider... hp: [2,6] # 2d6... ac: 16... attacks: [BITE, HURT]... """) Monster(name='Cave spider', hp=[2, 6], ac=16, attacks=['BITE', 'HURT'])>>> print yaml.dump(Monster( ... name='Cave lizard', hp=[3,6], ac=16, attacks=['BITE','HURT']))!Monster ac: 16attacks: [BITE, HURT] hp: [3, 6] name: Cave lizard
yaml.YAMLObject
使用元类魔术来注册构造函数,该构造函数将YAML节点转换为类实例,以及将类实例序列化到YAML节点的表示器。
如果你不想使用元类,你可以使用函数yaml.add_constructor
和注册你的构造函数和表示者yaml.add_representer
。例如,您可能需要为以下Dice
类添加构造函数和表示符:
>>> class Dice(tuple): ... def __new__(cls, a, b): ... return tuple.__new__(cls, [a, b]) ... def __repr__(self): ... return "Dice(%s,%s)" % self>>> print Dice(3,6) Dice(3,6)
Dice
对象的默认表示形式不是很漂亮:
>>> print yaml.dump(Dice(3,6))!!python/object/new:__main__.Dice- !!python/tuple [3, 6]
假设你想要一个Dice
对象AdB
在YAML中表示:
>>> print yaml.dump(Dice(3,6)) 3d6
首先,我们定义一个代表者,将一个骰子对象转换为一个标量节点!dice
,然后注册它。
>>> def dice_representer(dumper, data): ... return dumper.represent_scalar(u'!dice', u'%sd%s' % data)>>> yaml.add_representer(Dice, dice_representer)
现在你可以转储一个Dice
对象的实例:
>>> print yaml.dump({'gold': Dice(10,6)}) {gold: !dice '10d6'}
让我们添加代码来构建一个Dice对象:
>>> def dice_constructor(loader, node): ... value = loader.construct_scalar(node) ... a, b = map(int, value.split('d')) ... return Dice(a, b)>>> yaml.add_constructor(u'!dice', dice_constructor)
那么你也可以加载一个Dice
对象:
>>> print yaml.load("""... initial hit points: !dice 8d4... """) {'initial hit points': Dice(8,4)}
你可能不想在!dice
任何地方指定标签。有一种方法可以教PyYAML,看起来像XdY的任何未加标签的纯标量都有隐式标签!dice
。用途add_implicit_resolver
:
>>> import re>>> pattern = re.compile(r'^\d+d\d+$')>>> yaml.add_implicit_resolver(u'!dice', pattern)
现在,您不必指定标签来定义Dice
对象:
>>> print yaml.dump({'treasure': Dice(10,20)}) {treasure: 10d20}>>> print yaml.load("""... damage: 5d10... """) {'damage': Dice(5,10)}
YAML语法
YAML语法的一个很好的介绍是YAML规范的第2章。
你也可以检查YAML食谱。请注意,它专注于Ruby实现,并使用旧的YAML 1.0语法。
在这里,我们介绍最常见的YAML结构和相应的Python对象。
文件
YAML流是零个或多个文档的集合。一个空的流不包含任何文档。文件分开---
。文件可以有选择地结束...
。单个文档可能被标记或可能不被标记---
。
隐式文档的示例:
- Multimedia- Internet- Education
明确的文件的例子:
---- Afterstep- CTWM- Oroborus...
同一个流中的几个文档的示例:
---- Ada- APL- ASP- Assembly- Awk---- Basic---- C- C# # Note that comments are denoted with ' #' (space then #).- C++- Cold Fusion
块序列
在块上下文中,序列条目用-
(破折号然后空格)表示:
# YAML- The Dagger 'Narthanc'- The Dagger 'Nimthanc'- The Dagger 'Dethanc'
# Python["The Dagger 'Narthanc'", "The Dagger 'Nimthanc'", "The Dagger 'Dethanc'"]
块序列可以嵌套:
# YAML- - HTML - LaTeX - SGML - VRML - XML - YAML- - BSD - GNU Hurd - Linux
# Python[['HTML', 'LaTeX', 'SGML', 'VRML', 'XML', 'YAML'], ['BSD', 'GNU Hurd', 'Linux']]
不需要用新行开始嵌套序列:
# YAML- 1.1- - 2.1 - 2.2- - - 3.1- 3.2- 3.3
# Python[1.1, [2.1, 2.2], [[3.1, 3.2, 3.3]]]
块序列可嵌套到块映射。请注意,在这种情况下,不需要缩进序列。
# YAMLleft hand:- Ring of Teleportation- Ring of Speedright hand:- Ring of Resist Fire- Ring of Resist Cold- Ring of Resist Poison
# Python{'right hand': ['Ring of Resist Fire', 'Ring of Resist Cold', 'Ring of Resist Poison'],'left hand': ['Ring of Teleportation', 'Ring of Speed']}
块映射
在块上下文中,映射的键和值由:
(空格然后是空格)分隔开来:
# YAMLbase armor class: 0base damage: [4,4]plus to-hit: 12plus to-dam: 16plus to-ac: 0
# Python{'plus to-hit': 12, 'base damage': [4, 4], 'base armor class': 0, 'plus to-ac': 0, 'plus to-dam': 16}
复杂键用?
(问号然后空格)表示:
# YAML? !!python/tuple [0,0]: The Hero ? !!python/tuple [0,1]: Treasure ? !!python/tuple [1,0]: Treasure ? !!python/tuple [1,1]: The Dragon
# Python{(0, 1): 'Treasure', (1, 0): 'Treasure', (0, 0): 'The Hero', (1, 1): 'The Dragon'}
块映射可以嵌套:
# YAMLhero: hp: 34 sp: 8 level: 4orc: hp: 12 sp: 0 level: 2
# Python{'hero': {'hp': 34, 'sp': 8, 'level': 4}, 'orc': {'hp': 12, 'sp': 0, 'level': 2}}
块映射可以嵌套在块序列中:
# YAML- name: PyYAML status: 4 license: MIT language: Python- name: PySyck status: 5 license: BSD language: Python
# Python[{'status': 4, 'language': 'Python', 'name': 'PyYAML', 'license': 'MIT'}, {'status': 5, 'license': 'BSD', 'name': 'PySyck', 'language': 'Python'}]
流量收集
YAML中的流集合的语法非常接近Python中的列表和字典构造函数的语法:
# YAML{ str: [15, 17], con: [16, 16], dex: [17, 18], wis: [16, 16], int: [10, 13], chr: [5, 8] }
# Python{'dex': [17, 18], 'int': [10, 13], 'chr': [5, 8], 'wis': [16, 16], 'str': [15, 17], 'con': [16, 16]}
标量
YAML中有5种标量样式:简单,单引号,双引号,文字和折叠:
# YAMLplain: Scroll of Remove Cursesingle-quoted: 'EASY_KNOW'double-quoted: "?"literal: | # Borrowed from http://www.kersbergen.com/flump/religion.html by hjw ___ __ /.-.\ / )_____________\\ Y /_ /=== == === === =\ _\_ ( /)=== == === === == Y \ `-------------------( o ) \___/folded: > It removes all ordinary curses from all equipped items. Heavy or permanent curses are unaffected.
# Python{'plain': 'Scroll of Remove Curse','literal':'by hjw ___\n'' __ /.-.\\\n'' / )_____________\\\\ Y\n'' /_ /=== == === === =\\ _\\_\n''( /)=== == === === == Y \\\n'' `-------------------( o )\n'' \\___/\n','single-quoted': 'EASY_KNOW','double-quoted': '?','folded': 'It removes all ordinary curses from all equipped items. Heavy or permanent curses are unaffected.\n'}
每种风格都有自己的怪癖。一个简单的标量不使用指标来表示它的开始和结束,因此它是最受限制的风格。它的自然应用是属性和参数的名称。
使用单引号标量,可以表示任何不包含特殊字符的值。除了一对相邻的引号''
替换为一个单引号外,不会出现单引号标量的转义'
。
双引号是最强大的风格和唯一可以表达任何标量值的风格。双引号标量允许转义。使用转义序列\x*
和\u***
,你可以表达任何ASCII或Unicode字符。
有两种块标量样式:文字和折叠。字面风格是大块文本(如源代码)最适合的风格。折叠样式类似于文字样式,但两个相邻的非空行连接到由空格字符分隔的单个行。
别名
请注意,PyYAML还不支持递归对象。
使用YAML,您可以表示任意图形结构的对象。如果要从文档的不同部分引用同一个对象,则需要使用锚点和别名。
锚点由&
指标表示,而别名用``表示。例如,文件
left hand: &A name: The Bastard Sword of Eowyn weight: 30right hand: *A
表达了英雄双手握着重剑的想法。
PyYAML现在完全支持递归对象。例如,文件
&A [ *A ]
会产生一个包含对自身引用的列表对象。
标签
标签用于表示YAML节点的类型。标准的YAML标签在http://yaml.org/type/index.html定义。
标签可能是隐含的:
boolean: trueinteger: 3float: 3.14
{'boolean': True, 'integer': 3, 'float': 3.14}
或明确的:
boolean: !!bool "true"integer: !!int "3"float: !!float "3.14"
{'boolean': True, 'integer': 3, 'float': 3.14}
没有明确定义的标记的纯标量将受到隐式标记解析的影响。标量值将根据一组正则表达式进行检查,如果其中一个匹配,则将相应的标记分配给标量。PyYAML允许应用程序添加自定义隐式标签解析器。
YAML标签和Python类型
下表介绍了具有不同标记的节点如何转换为Python对象。
YAML标签 | Python类型 |
标准的YAML标签 | |
!!null |
None |
!!bool |
bool |
!!int |
int 或者long (int 在Python 3中) |
!!float |
float |
!!binary |
str (bytes 在Python 3中) |
!!timestamp |
datetime.datetime |
!!omap , !!pairs |
list 对 |
!!set |
set |
!!str |
str 或者unicode (str 在Python 3中) |
!!seq |
list |
!!map |
dict |
Python特定的标签 | |
!!python/none |
None |
!!python/bool |
bool |
!!python/bytes |
(bytes 在Python 3中) |
!!python/str |
str (str 在Python 3中) |
!!python/unicode |
unicode (str 在Python 3中) |
!!python/int |
int |
!!python/long |
long (int 在Python 3中) |
!!python/float |
float |
!!python/complex |
complex |
!!python/list |
list |
!!python/tuple |
tuple |
!!python/dict |
dict |
复杂的Python标签 | |
!!python/name:module.name |
module.name |
!!python/module:package.module |
package.module |
!!python/object:module.cls |
module.cls 例 |
!!python/object/new:module.cls |
module.cls 例 |
!!python/object/apply:module.f |
的价值 f(...) |
字符串转换(仅限Python 2)
有迹象表明,转换到四个标签str
和unicode
值:!!str
,!!binary
,!!python/str
,和!!python/unicode
。
!!str
str
如果它的值是ASCII,标记的标量将被转换为对象。否则,它被转换为unicode
。!!binary
标记的标量被转换为str
对象,其值使用base64编码进行解码。!!python/str
标量转换为str
用utf-8编码编码的对象。!!python/unicode
标量转换为unicode
对象。
相反,如果一个str
对象!!str
的值是ASCII,则它将被转换为一个标量。2. !!python/str
如果它的值是正确的utf-8序列,则为标量。3.另一个!!binary
标量。
如果unicode
对象!!python/unicode
的值是ASCII,则对象将转换为1. 标量。2.另一个!!str
标量。
字符串转换(仅限Python 3)
在Python 3中,str
对象被转换为!!str
标量和bytes
对象为!!binary
标量。出于兼容性考虑,标签!!python/str
和!!python/unicode
仍然支持并转换为str
对象。
名称和模块
为了表示像函数或类的静态Python对象,你需要使用一个复杂的!!python/name
标签。例如,该函数yaml.dump
可以表示为
!!python/name:yaml.dump
同样,模块使用标签来表示!python/module
:
!!python/module:yaml
对象
任何pickleable对象可以使用!!python/object
标签序列化:
!!python/object:module.Class { attribute: value, ... }
为了支持泡菜协议,提供了另外两种形式的!!python/object
标签:
!!python/object/new:module.Classargs: [argument, ...]kwds: {key: value, ...}state: ...listitems: [item, ...]dictitems: [key: value, ...]!!python/object/apply:module.functionargs: [argument, ...]kwds: {key: value, ...}state: ...listitems: [item, ...]dictitems: [key: value, ...]
如果只有该args
字段非空,则可以缩短上述记录:
!!python/object/new:module.Class [argument, ...]!!python/object/apply:module.function [argument, ...]
参考
警告:API稳定性不能保证!
yaml包
scan(stream, Loader=Loader)
scan(stream)
扫描给定stream
并产生一个令牌序列。
parse(stream, Loader=Loader) emit(events, stream=None, Dumper=Dumper, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None)
parse(stream)
解析给定的stream
并产生一系列解析事件。
emit(events, stream=None)
序列化给定的解析序列events
并将它们写入stream
。如果stream
是None
,则返回生成的流。
compose(stream, Loader=Loader) compose_all(stream, Loader=Loader) serialize(node, stream=None, Dumper=Dumper, encoding='utf-8', # encoding=None (Python 3)explicit_start=None, explicit_end=None, version=None, tags=None, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None) serialize_all(nodes, stream=None, Dumper=Dumper, ...)
compose(stream)
解析给定值stream
并返回流中第一个文档的表示图的根。如果流中没有文档,则返回None
。
compose_all(stream)
解析给定的stream
并返回与流中文档相对应的一系列表示图。
serialize(node, stream=None)
将给定的表示图形序列化为stream
。如果stream
是None
,则返回生成的流。
serialize_all(node, stream=None)
将给定的表示图的序列序列化为给定的stream
。如果stream
是None
,则返回生成的流。
load(stream, Loader=Loader) load_all(stream, Loader=Loader) safe_load(stream) safe_load_all(stream) dump(data, stream=None, Dumper=Dumper, default_style=None, default_flow_style=None, encoding='utf-8', # encoding=None (Python 3)explicit_start=None, explicit_end=None, version=None, tags=None, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None) dump_all(data, stream=None, Dumper=Dumper, ...) safe_dump(data, stream=None, ...) safe_dump_all(data, stream=None, ...)
load(stream)
解析给定的stream
并返回从流中第一个文档构造而来的Python对象。如果流中没有文档,则返回None
。
load_all(stream)
解析给定的stream
并返回与流中文档相对应的Python对象序列。
safe_load(stream)
解析给定的stream
并返回从流中第一个文档构造而来的Python对象。如果流中没有文档,则返回None
。safe_load
只识别标准的YAML标签,不能构造任意的Python对象。
一个python对象可以被标记为安全的,从而被识别yaml.safe_load
。为此,从yaml.YAMLObject
(如构造函数,表示者,解析器部分中所解释的)中派生它,并明确地将其类属性设置yaml_loader
为yaml.SafeLoader
。
safe_load_all(stream)
解析给定的stream
并返回与流中文档相对应的Python对象序列。safe_load_all
只识别标准的YAML标签,不能构造任意的Python对象。
dump(data, stream=None)
将给定的Python对象序列化为stream
。如果stream
是None
,则返回生成的流。
dump_all(data, stream=None)
将给定的Python对象序列序列化为给定的stream
。如果stream
是None
,则返回生成的流。每个对象都被表示为一个YAML文档。
safe_dump(data, stream=None)
将给定的Python对象序列化为stream
。如果stream
是None
,则返回生成的流。safe_dump
只产生标准的YAML标签,不能表示一个任意的Python对象。
safe_dump_all(data, stream=None)
将给定的Python对象序列序列化为给定的stream
。如果stream
是None
,则返回生成的流。每个对象都被表示为一个YAML文档。safe_dump_all
只产生标准的YAML标签,不能表示一个任意的Python对象。
def constructor(loader, node):# ...return datadef multi_constructor(loader, tag_suffix, node):# ...return data add_constructor(tag, constructor, Loader=Loader) add_multi_constructor(tag_prefix, multi_constructor, Loader=Loader)
add_constructor(tag, constructor)
指定一个constructor
给定的tag
。构造函数是将YAML表示图的节点转换为本地Python对象的函数。构造函数接受Loader
一个节点的实例并返回一个Python对象。
add_multi_constructor(tag_prefix, multi_constructor)
指定一个multi_constructor
给定的tag_prefix
。多构造函数是将YAML表示图的节点转换为本地Python对象的函数。多构造器接受Loader
节点标记的后缀和节点的实例,并返回一个Python对象。
def representer(dumper, data):# ...return nodedef multi_representer(dumper, data):# ...return node add_representer(data_type, representer, Dumper=Dumper) add_multi_representer(base_data_type, multi_representer, Dumper=Dumper)
add_representer(data_type, representer)
representer
为给定的Python对象指定一个data_type
。代表者是将本地Python对象转换为YAML表示图的节点的函数。代表者接受一个实例Dumper
和一个对象并返回一个节点。
add_multi_representer(base_data_type, multi_representer)
指定multi_representer
给定base_data_type
或其任何子类的Python对象。多表示器是将本地Python对象转换为YAML表示图的节点的函数。多表示者接受一个Dumper
对象的实例并返回一个节点。
add_implicit_resolver(tag, regexp, first, Loader=Loader, Dumper=Dumper) add_path_resolver(tag, path, kind, Loader=Loader, Dumper=Dumper)
add_implicit_resolver(tag, regexp, first)
为普通标量添加隐式标签解析器。如果标量值与给定值相匹配regexp
,则分配给它tag
。first
是可能的初始字符列表或None
。
add_path_resolver(tag, path, kind)
添加了一个基于路径的隐式标签解析器。A path
是在表示图形中形成节点路径的键列表。路径元素可以是字符串值,整数或None
。所述kind
的节点可以是str
,list
,dict
,或None
。
标记
Mark(name, index, line, column, buffer, pointer)
Mark
指向输入流中某个位置的实例。name
是流的名称,例如,如果输入流是文件,则它可以是文件名。line
并且column
是该位置的行和列(从0开始)。buffer
当它不是的时候None
,是包含该位置的输入流的一部分,并且pointer
指的是位置buffer
。
YAMLError
YAMLError()
如果YAML解析器遇到错误情况,则会引发一个异常,该异常是YAMLError
其子类的一个实例。应用程序可能会捕获此异常并警告用户。
try: config = yaml.load(file('config.yaml', 'r'))except yaml.YAMLError, exc:print "Error in configuration file:", exc
YAML处理器产生的异常可能指向有问题的位置。
>>> try: ... yaml.load("unbalanced blackets: ][") ... except yaml.YAMLError, exc: ... if hasattr(exc, 'problem_mark'): ... mark = exc.problem_mark ... print "Error position: (%s:%s)" % (mark.line+1, mark.column+1) Error position: (1:22)
令牌
令牌由YAML扫描仪生成。除了低级YAML应用程序(如语法突出显示)之外,它们并不是真正有用的。
PyYAML扫描器产生以下类型的标记:
StreamStartToken(encoding, start_mark, end_mark) # Start of the stream.StreamEndToken(start_mark, end_mark) # End of the stream.DirectiveToken(name, value, start_mark, end_mark) # YAML directive, either %YAML or %TAG.DocumentStartToken(start_mark, end_mark) # '---'.DocumentEndToken(start_mark, end_mark) # '...'.BlockSequenceStartToken(start_mark, end_mark) # Start of a new block sequence.BlockMappingStartToken(start_mark, end_mark) # Start of a new block mapping.BlockEndToken(start_mark, end_mark) # End of a block collection.FlowSequenceStartToken(start_mark, end_mark) # '['.FlowMappingStartToken(start_mark, end_mark) # '{'.FlowSequenceEndToken(start_mark, end_mark) # ']'.FlowMappingEndToken(start_mark, end_mark) # '}'.KeyToken(start_mark, end_mark) # Either '?' or start of a simple key.ValueToken(start_mark, end_mark) # ':'.BlockEntryToken(start_mark, end_mark) # '-'.FlowEntryToken(start_mark, end_mark) # ','.AliasToken(value, start_mark, end_mark) # '*value'.AnchorToken(value, start_mark, end_mark) # '&value'.TagToken(value, start_mark, end_mark) # '!value'.ScalarToken(value, plain, style, start_mark, end_mark) # 'value'.
start_mark
并end_mark
表示令牌的开始和结束。
例:
>>> document = """... ---... block sequence:... - BlockEntryToken... block mapping:... ? KeyToken... : ValueToken... flow sequence: [FlowEntryToken, FlowEntryToken]... flow mapping: {KeyToken: ValueToken}... anchors and tags:... - &A !!int '5'... - *A... ...... """>>> for token in yaml.scan(document): ... print token StreamStartToken(encoding='utf-8') DocumentStartToken() BlockMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value=u'block sequence') ValueToken() BlockEntryToken() ScalarToken(plain=True, style=None, value=u'BlockEntryToken') KeyToken() ScalarToken(plain=True, style=None, value=u'block mapping') ValueToken() BlockMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value=u'KeyToken') ValueToken() ScalarToken(plain=True, style=None, value=u'ValueToken') BlockEndToken() KeyToken() ScalarToken(plain=True, style=None, value=u'flow sequence') ValueToken() FlowSequenceStartToken() ScalarToken(plain=True, style=None, value=u'FlowEntryToken') FlowEntryToken() ScalarToken(plain=True, style=None, value=u'FlowEntryToken') FlowSequenceEndToken() KeyToken() ScalarToken(plain=True, style=None, value=u'flow mapping') ValueToken() FlowMappingStartToken() KeyToken() ScalarToken(plain=True, style=None, value=u'KeyToken') ValueToken() ScalarToken(plain=True, style=None, value=u'ValueToken') FlowMappingEndToken() KeyToken() ScalarToken(plain=True, style=None, value=u'anchors and tags') ValueToken() BlockEntryToken() AnchorToken(value=u'A') TagToken(value=(u'!!', u'int')) ScalarToken(plain=False, style="'", value=u'5') BlockEntryToken() AliasToken(value=u'A') BlockEndToken() DocumentEndToken() StreamEndToken()
活动
事件由低级解析器和发射器接口使用,与SAX API类似。当解析器解析YAML流并产生一系列事件时,Emitter接受一系列事件并发出一个YAML流。
以下事件被定义:
StreamStartEvent(encoding, start_mark, end_mark) StreamEndEvent(start_mark, end_mark) DocumentStartEvent(explicit, version, tags, start_mark, end_mark) DocumentEndEvent(start_mark, end_mark) SequenceStartEvent(anchor, tag, implicit, flow_style, start_mark, end_mark) SequenceEndEvent(start_mark, end_mark) MappingStartEvent(anchor, tag, implicit, flow_style, start_mark, end_mark) MappingEndEvent(start_mark, end_mark) AliasEvent(anchor, start_mark, end_mark) ScalarEvent(anchor, tag, implicit, value, style, start_mark, end_mark)
该flow_style
标志指示集合是阻止还是流动。可能的值是None
,True
,False
。style
标量事件的标志表示标量的样式。可能的值是None
,_
,'\_
,'"'
,'|'
,'>'
。implicit
收集开始事件的标志指示在发射收集时是否可以省略标签。implicit
标量事件的标志是一对布尔值,表示当标量以相应的普通和非普通样式发射时标记是否可以省略。
例:
>>> document = """... scalar: &A !!int '5'... alias: *A... sequence: [1, 2, 3]... mapping: [1: one, 2: two, 3: three]... """>>> for event in yaml.parse(document): ... print event StreamStartEvent() DocumentStartEvent() MappingStartEvent(anchor=None, tag=None, implicit=True) ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'scalar') ScalarEvent(anchor=u'A', tag=u'tag:yaml.org,2002:int', implicit=(False, False), value=u'5') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'alias') AliasEvent(anchor=u'A') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'sequence') SequenceStartEvent(anchor=None, tag=None, implicit=True) ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'1') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'2') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'3') SequenceEndEvent() ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'mapping') MappingStartEvent(anchor=None, tag=None, implicit=True) ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'1') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'one') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'2') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'two') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'3') ScalarEvent(anchor=None, tag=None, implicit=(True, False), value=u'three') MappingEndEvent() MappingEndEvent() DocumentEndEvent() StreamEndEvent()>>> print yaml.emit([ ... yaml.StreamStartEvent(encoding='utf-8'), ... yaml.DocumentStartEvent(explicit=True), ... yaml.MappingStartEvent(anchor=None, tag=u'tag:yaml.org,2002:map', implicit=True, flow_style=False), ... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'agile languages'), ... yaml.SequenceStartEvent(anchor=None, tag=u'tag:yaml.org,2002:seq', implicit=True, flow_style=True), ... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'Python'), ... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'Perl'), ... yaml.ScalarEvent(anchor=None, tag=u'tag:yaml.org,2002:str', implicit=(True, True), value=u'Ruby'), ... yaml.SequenceEndEvent(), ... yaml.MappingEndEvent(), ... yaml.DocumentEndEvent(explicit=True), ... yaml.StreamEndEvent(), ... ])---agile languages: [Python, Perl, Ruby] ...
节点
节点是YAML信息模型中的实体。有三种节点:标量,序列和映射。在PyYAML中,节点由Composer生成,可以通过Serializer序列化为YAML流。
ScalarNode(tag, value, style, start_mark, end_mark) SequenceNode(tag, value, flow_style, start_mark, end_mark) MappingNode(tag, value, flow_style, start_mark, end_mark)
在style
和flow_style
标志的含义事件相同。标量节点的值必须是unicode字符串。序列节点的值是一个节点列表。映射节点的值是由键和值节点组成的一对列表。
例:
>>> print yaml.compose("""... kinds:... - scalar... - sequence... - mapping... """) MappingNode(tag=u'tag:yaml.org,2002:map', value=[ (ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'kinds'), SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[ ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'scalar'), ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'sequence'), ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'mapping')]))])>>> print yaml.serialize(yaml.SequenceNode(tag=u'tag:yaml.org,2002:seq', value=[ ... yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'scalar'), ... yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'sequence'), ... yaml.ScalarNode(tag=u'tag:yaml.org,2002:str', value=u'mapping')]))- scalar- sequence- mapping
装载机
Loader(stream) SafeLoader(stream) BaseLoader(stream)# The following classes are available only if you build LibYAML bindings.CLoader(stream) CSafeLoader(stream) CBaseLoader(stream)
Loader(stream)
是上述类中最常见的,应该在大多数情况下使用。stream
是一个输入YAML流。它可以是一个字符串,一个Unicode字符串,一个打开的文件,一个开放的Unicode文件。
Loader
支持所有预定义的标签,可以构造一个任意的Python对象。因此,使用Loader
从不受信任的来源加载文档是不安全的。默认情况下,该功能scan
,parse
,compose
,construct
,和其他人使用Loader
。
SafeLoader(stream)
仅支持标准的YAML标签,因此它不会构造类实例,并且可能安全地使用从不可信源接收的文档。用于解析流的函数safe_load
和safe_load_all
用法SafeLoader
。
BaseLoader(stream)
不解析或支持任何标签,只构造基本的Python对象:列表,字典和Unicode字符串。
CLoader
,CSafeLoader
,CBaseLoader
是使用C语言编写的上述类别的版本LibYAML库。
Loader.check_token(*TokenClasses) Loader.peek_token() Loader.get_token()
Loader.check_token(*TokenClasses)
True
如果流中的下一个标记是给定的其中一个实例,则返回TokenClasses
。否则它返回False
。
Loader.peek_token()
返回流中的下一个标记,但不会将其从内部标记队列中删除。该函数返回None
流的结尾。
Loader.get_token()
返回流中的下一个标记,并将其从内部标记队列中删除。该函数返回None
流的结尾。
Loader.check_event(*EventClasses) Loader.peek_event() Loader.get_event()
Loader.check_event(*EventClasses)
True
如果流中的下一个事件是给定的其中一个实例,则返回EventClasses
。否则它返回False
。
Loader.peek_event()
返回流中的下一个事件,但不会将其从内部事件队列中删除。该函数返回None
流的结尾。
Loader.get_event()
返回流中的下一个事件,并将其从内部事件队列中移除。该函数返回None
流的结尾。
Loader.check_node() Loader.get_node()
Loader.check_node()
返回的True
是流中有更多的文档可用。否则它返回False
。
Loader.get_node()
构造流中下一个文档的表示图并返回其根节点。
Loader.check_data() Loader.get_data() Loader.add_constructor(tag, constructor) # Loader.add_constructor is a class method.Loader.add_multi_constructor(tag_prefix, multi_constructor) # Loader.add_multi_constructor is a class method.Loader.construct_scalar(node) Loader.construct_sequence(node) Loader.construct_mapping(node)
Loader.check_data()
返回的True
是流中有更多的文档可用。否则它返回False
。
Loader.get_data()
构造并返回与流中下一个文档相对应的Python对象。
Loader.add_constructor(tag, constructor)
:看add_constructor
。
Loader.add_multi_constructor(tag_prefix, multi_constructor)
:看add_multi_constructor
。
Loader.construct_scalar(node)
检查给定的node
是一个标量并返回它的值。这个函数打算在构造函数中使用。
Loader.construct_sequence(node)
检查给定的node
是一个序列,并返回与节点项对应的Python对象列表。这个函数打算在构造函数中使用。
Loader.construct_mapping(node)
检查给定的node
是一个映射,并返回对应于节点键和值的Python对象的字典。这个函数打算在构造函数中使用。
Loader.add_implicit_resolver(tag, regexp, first) # Loader.add_implicit_resolver is a class method.Loader.add_path_resolver(tag, path, kind) # Loader.add_path_resolver is a class method.
Loader.add_implicit_resolver(tag, regexp, first)
:看add_implicit_resolver
。
Loader.add_path_resolver(tag, path, kind)
:看add_path_resolver
。
自卸车
Dumper(stream, default_style=None, default_flow_style=None, canonical=None, indent=None, width=None, allow_unicode=None, line_break=None, encoding=None, explicit_start=None, explicit_end=None, version=None, tags=None) SafeDumper(stream, ...) BaseDumper(stream, ...)# The following classes are available only if you build LibYAML bindings.CDumper(stream, ...) CSafeDumper(stream, ...) CBaseDumper(stream, ...)
Dumper(stream)
是上述类中最常见的,应该在大多数情况下使用。stream
是一个输出YAML流。它可以是一个开放的文件或一个开放的Unicode文件。
Dumper
支持所有预定义的标签,可以代表一个任意的Python对象。因此它可能产生一个不能被其他YAML处理器加载的文档。默认情况下,该功能emit
,serialize
,dump
,和其他人使用Dumper
。
SafeDumper(stream)
只生成标准的YAML标签,因此不能表示类实例,可能与其他YAML处理器更兼容。用于生成YAML文档的功能safe_dump
和safe_dump_all
用途SafeDumper
。
BaseDumper(stream)
不支持任何标签,仅用于子类化。
CDumper
,CSafeDumper
,CBaseDumper
是使用C语言编写的上述类别的版本LibYAML库。
Dumper.emit(event)
Dumper.emit(event)
将给定的序列化event
并将其写入输出流。
Dumper.open() Dumper.serialize(node) Dumper.close()
Dumper.open()
发出StreamStartEvent
。
Dumper.serialize(node)
将给定的表示图形串行化到输出流中。
Dumper.close()
发出StreamEndEvent
。
Dumper.represent(data) Dumper.add_representer(data_type, representer) # Dumper.add_representer is a class method.Dumper.add_multi_representer(base_data_type, multi_representer) # Dumper.add_multi_representer is a class method.Dumper.represent_scalar(tag, value, style=None) Dumper.represent_sequence(tag, value, flow_style=None) Dumper.represent_mapping(tag, value, flow_style=None)
Dumper.represent(data)
将给定的Python对象序列化为输出YAML流。
Dumper.add_representer(data_type, representer)
:看add_representer
。
Dumper.add_multi_representer(base_data_type, multi_representer)
:看add_multi_representer
。
Dumper.represent_scalar(tag, value, style=None)
返回给定标节点tag
,value
和style
。此功能旨在用于代表人员。
Dumper.represent_sequence(tag, sequence, flow_style=None)
返回给定子节点和给定子tag
节点所生成的子节点sequence
。
Dumper.represent_mapping(tag, mapping, flow_style=None)
返回一个映射节点,其中给定子节点和给定子tag
节点的值由给定子节点生成mapping
。
Dumper.add_implicit_resolver(tag, regexp, first) # Dumper.add_implicit_resolver is a class method.Dumper.add_path_resolver(tag, path, kind) # Dumper.add_path_resolver is a class method.
Dumper.add_implicit_resolver(tag, regexp, first)
:看add_implicit_resolver
。
Dumper.add_path_resolver(tag, path, kind)
:看add_path_resolver
。
YAMLObject
class MyYAMLObject(YAMLObject): yaml_loader = Loader yaml_dumper = Dumper yaml_tag = u'...'yaml_flow_style = ...@classmethoddef from_yaml(cls, loader, node):# ...return data@classmethoddef to_yaml(cls, dumper, data):# ...return node
子类化YAMLObject
是为类定义标签,构造函数和表示符的简单方法。您只需要覆盖该yaml_tag
属性。如果要定义自定义构造函数和申述,重新定义from_yaml
和to_yaml
方法相应。
偏离规范
需要更新本节
YAML中制表符的规则令人困惑。我们很近,但还没有。也许规范和解析器都应该被修复。无论如何,在YAML制表符的最好的规则是根本不使用它们。
字节顺序标记。最初的BOM被剥离,但是流内的BOM被视为内容的一部分。它可以修复,但现在并不重要。
如果指定了别名或标记,则不允许使用空纯标量。这样做是为了防止像[!tag,value]这样的异常,它可以解释为[!值]和[!“”,“价值”]。规范应该是固定的。流收集的缩进。规范要求它们比块父节点缩进更多。不幸的是,这个规则使许多直观正确的构造无效,例如,
block: { } # this is indentation violation according to the spec.
流动模式下不允许使用“:”标记。
{1:2}被解释为{1:2}。
本文转自506554897 51CTO博客,原文链接:http://blog.51cto.com/506554897/1984140,如需转载请自行联系原作者