Python YAML解析器
在本教程中,我们将学习如何使用Python读取、写入或执行YAML文件的各种操作。我们将讨论YAML文件格式、使用方法以及如何使用Python对其进行操作。
让我们简要介绍一下YAML。
什么是YAML
YAML是”Yet Another Markup Language”的缩写。它以序列化的方式存储配置文件数据,近年来它在使用中越来越受欢迎,因为它是一种可读性强的数据格式,通常用于数据存储或传输。
YAML支持三种数据类型-标量(字符串、整数和浮点数)、列表和关联数组。
YAML文件的扩展名为.yaml或.yml。我们可以使用”#”符号在YAML中添加注释。每个子项之前都要有一个连字符。值可以使用缩进进行嵌套。
YAML的优势
YAML的一些重要优点如下。
- 所有编程语言都支持YAML- 我们只需要用一种语言编写YAML,就可以在几乎所有编程语言中使用,无需进行任何修改。
- 对象序列化- 我们可以对YAML数据格式进行序列化。
- 易于阅读- 创建YAML文件没有固定的规则。简单的缩进用于定义单个块和文档。
在继续之前,我们假设您对Python有基本的了解,或者具有初学者级别的Python编程经验。
PyYAML模块
PyYAML是一个Python模块,它提供了一系列方法来执行YAML文件上的多种操作。我们可以轻松地将YAML文件转换为字典并读取其内容。借助YAML模块的帮助,我们可以读写复杂的配置YAML文件,序列化和持久化YAML数据。
要使用PyYAML,我们需要在系统中安装它。以下是PyYAML模块的安装步骤。
安装PyYAML
我们可以使用以下方法进行安装。
- 使用pip命令安装
- 通过源代码安装
使用pip命令
我们可以使用pip命令进行安装。在终端中输入以下命令来安装PyYAML模块。
pip install pyyaml
通过源代码安装
如果使用pip命令时遇到错误,我们可以使用另一种安装方式。按照以下指示进行操作。
- 打开PyYAML Github存储库,点击代码部分并下载ZIP文件。
- 解压下载的ZIP文件。
- 现在打开终端并切换到ZIP文件解压后的目录。
- 现在运行python setup.py命令,然后按回车键。它将在你的计算机中安装PyYAML模块。
读取YAML文件
首先,我们创建一个新的YAML文件,命名为 sample.yaml 文件,将使用PyYAML模块来读取它。
sample.py
# YAML Document starts with ---
# Comments start with #
UserName: Antonio
Password: fire123 *
phone: 9879098
Skills:
-Python
-SQL
-Django
-Rest Framework
-JavaScript
yaml.load()方法用于读取YAML文件。该方法解析并将YAML对象转换为Python字典,以便我们可以轻松读取内容。这个过程称为将YAML文件反序列化为Python。
load()方法接受一个参数,可以是字节字符串、打开的二进制文件对象、Unicode字符串或打开的YAML文件对象。
如果将文件或字节字符串作为参数传递,它应该编码为utf-8、utf-16-be或utf-16-le。
让我们来看下面的示例。
示例
import yaml
from yaml.loader import SafeLoader
#open yaml file in read mode
with open('sample.yaml', 'r') as f:
data = list(yaml.load(f, Loader=SafeLoader))
print(data)
输出:
[{'UserName': 'Antonio', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}]
解释 –
我们在上面的代码中导入了yaml及其Loader来读取YAML文件。load()函数带有四种类型的Loader。
- SafeLoader – 我们在上面的示例中使用了这个Loader。它安全地加载YAML的一个子集。当输入来自不受信任的来源时,它通常用于加载数据。
- BaseLoader – 它将所有基本的YAML标量加载为字符串。
- FullLoader – 它与BaseLoader的工作方式相同,但避免了任意代码执行。如果输入来自不受信任的来源,它可能会存在安全威胁。
- UnsafeLoader – 它是不受信任的来源输入的推荐Loader,并且通常用于向后兼容性。
load()方法返回我们将其类型转换为列表并且可以访问任何元素的生成器对象。
我们还可以以字典形式获得相同的值。让我们了解以下示例。
我们还可以以字典的形式获取yaml值。让我们了解以下示例。
示例2
import yaml
from yaml.loader import FullLoader
#open yaml file in read
with open('sample.yaml', 'r') as f:
yaml_data = yaml.load(f, Loader=FullLoader)
print(yaml_data)
输出:
{'UserName': 'Antonio', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}
我们将标量参数SafeLoader更改为 FullLoader ,将YAML数据转换为字典。此加载程序的优点是,我们无需将加载的数据强制转换为列表。
读取多个YAML文档
我们可以使用 yaml.load_all() 方法读取多个yaml文档。单个YAML文件可以有多个文档。下面是单个文件中多个文档的示例。
sample.yaml
---
UserName: Antonio
Password: fire123 *
phone: 9879098
Skills:
-Python
-SQL
-Django
-Rest Framework
-JavaScript
...
---
UserName: Maino
Password: fire123 *
phone: 9879098
Skills:
-Python
-SQL
-Django
-Rest Framework
-JavaScript
...
---
UserName: George
Password: fire123 *
phone: 9879098
Skills:
-Python
-SQL
-Django
-Rest Framework
-JavaScript
...
文档以三个破折号(—)开头,并以三个点(…)结尾。让我们理解以下示例。
示例
import yaml
from yaml.loader import SafeLoader
#open yaml file in read
with open('sample.yaml', 'r') as f:
yaml_data = list(yaml.load_all(f, Loader=SafeLoader))
print(yaml_data)
输出:
[{'UserName': 'Antonio', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}, {'UserName': 'Maino', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}, {'UserName': 'George', 'Password': 'fire123 *', 'phone': 9879098, 'Skills': '-Python -SQL -Django -Rest Framework -JavaScript'}]
解释:
load() 方法返回了一个生成器对象,我们将其强制转换为列表以便访问任何元素。在之前的示例中,我们学习了如何读取YAML文件。现在,我们将学习如何将数据转储到YAML文件中。
使用PyYAML模块写入YAML文件
将Python数据转储为YAML称为序列化。要将数据转储到YAML文件中,我们将使用 yaml.dump() 方法。让我们理解以下示例。
示例:
import yaml
# dict object
members = [{'User': 'Zoey', 'Password': 'Xavier@123', 'Phone': 345464, 'Skills': ['Python', 'SQL', 'Django', 'Rest Framework', 'JavaScript']},
{'name': 'Zaara', 'occupation': 'Dentist'}]
# Convert Python dictionary into a YAML document
print(yaml.dump(members))
输出:
Password: Xavier@123
Phone: 345464
Skills:
- Python
- SQL
- Django
- Rest Framework
- JavaScript
User: Zoey
- name: Zaara
occupation: Dentist
说明 –
dump() 方法将Python对象转换为YAML格式,并将其写入YAML文件中。我们在上面的示例中也是这样做的。 dump() 方法接受两个参数 – data和stream。
data参数表示要转换为YAML流的Python对象。第二个参数是一个文件,它必须是文本或二进制文件。YAML流数据将被写入给定的文件名中;否则, dump() 将返回生成的文档。
让我们来了解一下在文件中写入Python数据的示例。
示例2:
import yaml
# dict object
python_data = [{'User': 'Zoey', 'Password': 'Xavier@123', 'Phone': 345464, 'Skills': ['Python', 'SQL', 'Django', 'Rest Framework', 'JavaScript']},
{'name': 'Zaara', 'occupation': 'Dentist'}]
with open('NewDetails.yaml', 'w') as f:
data = yaml.dump(python_data, f, sort_keys=False, default_flow_style=False)
输出:
NewDetails.yaml
- User: Zoey
Password: Xavier@123
Phone: 345464
Skills:
- Python
- SQL
- Django
- Rest Framework
- JavaScript
- name: Zaara
occupation: Dentist
说明
在上面的示例中,首先我们定义了要写入文件的Python字典。然后,我们以写模式打开新的details.YAML文件。我们使用了dump()方法,并传递了Python字典对象和其他两个标签。这些标签是 –
- default_flow_style - 它用于以正确的缩进显示嵌套块的内容。默认情况下,它为 True 。如果我们将其值设置为false,并且嵌套列表内部的值以流样式显示,则会以正确的缩进显示块样式的内容。
- sort_keys - 它用于按字母顺序对键进行排序。默认情况下,它为 True 。如果我们将其值设置为false,它将保持插入顺序。
dump多个YAML文档
使用 yaml.dump_all() 方法将多个YAML文档倾入单个流中。此方法接受一个列表或产生Python对象的生成器,用于将其序列化为YAML文档,以及第二个可选参数作为打开的文件。
让我们理解以下示例。
示例
import yaml
# dict object
python_data = [{'User': 'Zoey', 'Password': 'Xavier@123', 'Phone': 345464, 'Skills': ['Python', 'SQL', 'Django', 'Rest Framework', 'JavaScript']},
{'name': 'Zaara', 'occupation': 'Software Engineer'}]
data1 = yaml.dump(python_data)
print("Using dump() method")
print(data1)
data2 = yaml.dump_all(python_data)
print("Using dump_all() method")
print(data2)
输出:
Using dump() method
- Password: Xavier@123
Phone: 345464
Skills:
- Python
- SQL
- Django
- Rest Framework
- JavaScript
User: Zoey
- name: Zaara
occupation: Dentist
Using dump_all() method
Password: Xavier@123
Phone: 345464
Skills:
- Python
- SQL
- Django
- Rest Framework
- JavaScript
User: Zoey
---
name: Zaara
occupation: Dentist
Python YAML排序键
sort_keys是一个可选的标签,用于将Python数据转储到文件中。如果我们将其设置为True,则会按字母顺序对YAML文档的所有键进行排序。让我们了解以下示例。
示例
import yaml
from yaml.loader import FullLoader
#open yaml file in read
with open('sample.yaml', 'r') as f:
print("Before Sorting?..")
yaml_data = yaml.load(f, Loader=FullLoader)
print(yaml_data)
print("After Sorting......")
sorted_data = yaml.dump(yaml_data, sort_keys=True)
print(sorted_data)
输出:
import yaml
from yaml.loader import FullLoader
#open yaml file in read
with open('sample.yaml', 'r') as f:
print("Before Sorting?..")
yaml_data = yaml.load(f, Loader=FullLoader)
print(yaml_data)
print("After Sorting......")
sorted_data = yaml.dump(yaml_data, sort_keys=True)
print(sorted_data)
格式化YAML文件
PyYaml模块在写入YAML文档时提供了格式化YAML文件的功能。dump()方法支持各种格式化参数。以下是格式化参数。
参数 –
- indent – 它帮助设置首选的缩进。
- width – 它帮助设置首选的宽度。
- canonical = True – 它强制使用首选的样式来处理标量和集合。
让我们理解以下示例 –
示例
import yaml
from yaml.loader import FullLoader
#open yaml file in read
with open('sample.yaml', 'r') as f:
yaml_data = yaml.load(f, Loader=FullLoader)
sorted_data = yaml.dump(yaml_data, indent=10, default_flow_style=False)
print(sorted_data)
输出:
Password: fire123 *
Skills: -Python -SQL -Django -Rest Framework -JavaScript
UserName: Antonio
phone: 9879098
自定义 Python 类 YAML 可序列化
我们可以创建自定义 Python 类,将 YAML 转换为自定义 Python 对象,而不是列表或内置类型。
让我们理解以下示例 –
示例
import yaml
from yaml.loader import UnsafeLoader
class Person:
def __init__(self, user, password):
self.user = user
self.password = password
def __repr__(self):
return "%s(user=%r, password=%r)" % (
self.__class__.__name__, self.user, self.password)
# Make Python Class YAML Serializable
person = Person('Jessa', 'queue@123')
yaml_obj = yaml.dump(person)
# Deserialize YAML into a Custom Python Class
new_person = yaml.load(yaml_obj, Loader=UnsafeLoader)
print(new_person.user, new_person.password)
输出:
Jessa queue@123
使用PyYAML创建自定义标签
我们可以根据应用程序的要求创建自定义标签,并在解析YAML文件时为自定义标签分配默认值。为此,涉及以下几个步骤。
- 在步骤1中,我们定义一个接受loader和YAML节点的构造函数。
- 我们在创建的构造函数中调用constuct_mapping()方法,该方法将返回与YAML节点对应的Python字典。它将返回带有该字典的构造函数。
- 返回的构造函数将传递给add_constructor(),该函数将YAML表示图转换为本地Python对象。构造函数接受Loader的实例和一个节点,并返回Python对象。
- 现在,load()方法可以在add_constructor()中定义的相同自定义标签下接受许多字段,没有值的字段将被分配在init()方法中定义的默认值。
让我们理解以下示例。
示例
import yaml
def custom_constructor(loader, node) :
fields = loader.construct_mapping(node)
return Test(**fields)
yaml.add_constructor('!Custom Tags', custom_constructor)
class Test(object) :
def __init__(self, user, password, phone=11000) :
self.user = user
self.password = password
self.phone = phone
def __repr__(self):
return "%s(user=%s, password=%r,phone=%r)" % (self.__class__.__name__, self.user, self.password, self.phone)
print (yaml.load("""
- !Custom Tags { user: 'Sam' }
- !Custom Tags { user: 'Gaby', password: 'admin@123',phone: 5656}"""))
输出:
[Custom Tags(user=Sam, password=new@123,phone=1100), Test(name=Gaby, password= admin@123, phone=5656)]
PyYAML模块中的转换表
以下是PyYAML模块使用的表格,用于将Python对象转换为相应的YAML。在编码时, dump() 方法使用转换。
YAML 标记 | Python 类型 |
---|---|
!!null | None |
!!bool | Bool |
!!float | Float |
!!int | Int |
!!binary | str (Python3中的bytes) |
!!timestamp | Datetime.datetime |
!!omap, !!pairs | 键值对列表 |
!!set | Set |
!!seq | 列表 |
!!str | str 或 unicode (Python中的str) |
!!map | dict |
YAML错误
YAML解析器在出现错误时会引发一个名为 YAMLError 的异常。通过这个错误,我们可以调试问题。因此建议将YAML序列化代码放在try-except块中使用。让我们来看下面的示例。
示例
import yaml
try:
config = yaml.load('Userdetails.yaml')
except yaml.YAMLError:
print("Error in configuration file:")
令牌
令牌通常在低级应用程序中使用,如语法高亮。我们可以使用 scan() 方法生成一组令牌。让我们来看下面的示例。
示例
import yaml
with open('sample.yaml') as f:
data = yaml.scan(f, Loader=yaml.FullLoader)
for token in data:
print(token)
输出:
StreamStartToken(encoding=None)
DocumentStartToken()
BlockMappingStartToken()
KeyToken()
ScalarToken(plain=True, style=None, value='UserName')
ValueToken()
ScalarToken(plain=True, style=None, value='Antonio')
KeyToken()
ScalarToken(plain=True, style=None, value='Password')
ValueToken()
ScalarToken(plain=True, style=None, value='fire123 *')
KeyToken()
ScalarToken(plain=True, style=None, value='phone')
ValueToken()
ScalarToken(plain=True, style=None, value='9879098')
KeyToken()
ScalarToken(plain=True, style=None, value='Skills')
ValueToken()
ScalarToken(plain=True, style=None, value='-Python -SQL -Django -Rest Framework -JavaScript')
BlockEndToken()
DocumentEndToken()
StreamEndToken()
Python YAML to XML
YAML数据可以使用XMLPlain模块转换为XML格式。XML是“eXtensible Markup Language”的缩写,使用HTML标签来定义标签。
使用obj_from_yaml()方法可以从YAML流或字符串生成XML plain对象。为了保持XML plain对象元素的顺序,YAML流被存储为OrderDict。
让我们来看一个包含员工详细信息的示例YAML文件,并将其转换为XML文件。
示例
StudentRecord:
-Student:
'rollno': st01
name: Alexa
class: 10
subject: python, Java
-Student:
'rollno': st02
name: Prince
class: 11
subject: Webservices, REST API
让我们理解代码实现。
示例
import xmlplain
# Read the YAML file
with open("student.yaml") as inf:
root = xmlplain.obj_from_yaml(inf)
# Output back XML
with open("student.xml", "w") as outf:
xmlplain.xml_from_obj(root, outf, pretty=True)
结论
在本教程中,我们学习了YAML和PyYAML模块的一些重要概念。我们介绍了如何创建自定义标签,将YAML文件的内容加载到我们的Python程序中作为字典。我们还讨论了如何操作YAML格式的文件。本教程只包含了库的简要和基本功能。