Python之ruamel.yaml模块详解(二)

简介: Python之ruamel.yaml模块详解(二)

4 将YAML解析为Python对象并修改

import sys
from ruamel.yaml import YAML

inp = """\
# example
name:
  # details
  family: Smith   # very common
  given: Alice    # one of the siblings
"""

yaml = YAML()
code = yaml.load(inp)
code['name']['given'] = 'Bob'

yaml.dump(code, sys.stdout)
  • 结果是:
# example
name:
  # details
  family: Smith   # very common
  given: Bob      # one of the siblings

5 使用旧API将YAML解析为Python对象并修改

from __future__ import print_function

import sys
import ruamel.yaml

inp = """\
# example
name:
  # details
  family: Smith   # very common
  given: Alice    # one of the siblings
"""

code = ruamel.yaml.load(inp, ruamel.yaml.RoundTripLoader)
code['name']['given'] = 'Bob'

ruamel.yaml.dump(code, sys.stdout, Dumper=ruamel.yaml.RoundTripDumper)

# the last statement can be done less efficient in time and memory with
# leaving out the end='' would cause a double newline at the end
# print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='')
  • 结果是:
# example
name:
  # details
  family: Smith   # very common
  given: Bob      # one of the siblings

6 使用[]和.get()访问合并的键:

from ruamel.yaml import YAML

inp = """\
- &CENTER {x: 1, y: 2}
- &LEFT {x: 0, y: 2}
- &BIG {r: 10}
- &SMALL {r: 1}
# All the following maps are equal:
# Explicit keys
- x: 1
  y: 2
  r: 10
  label: center/big
# Merge one map
- <<: *CENTER
  r: 10
  label: center/big
# Merge multiple maps
- <<: [*CENTER, *BIG]
  label: center/big
# Override
- <<: [*BIG, *LEFT, *SMALL]
  x: 1
  label: center/big
"""


def func():
    yaml = YAML()
    data = yaml.load(inp)
    print(data)
    print(data[7]['y'])
    assert data[7]['y'] == 2
 

if __name__ == "__main__":
    func()
  • 结果是:
[ordereddict([('x', 1), ('y', 2)]), 
ordereddict([('x', 0), ('y', 2)]), 
ordereddict([('r', 10)]), 
ordereddict([('r', 1)]), 
ordereddict([('x', 1), ('y', 2), ('r', 10), ('label', 'center/big')]), ordereddict([('r', 10), ('label', 'center/big'), ('x', 1), ('y', 2)]), ordereddict([('label', 'center/big'), ('x', 1), ('y', 2), ('r', 10)]), ordereddict([('x', 1), ('label', 'center/big'), ('r', 10), ('y', 2)])]
2
  • 使用.get()方法,如下:
from ruamel.yaml import YAML

inp = """\
- &CENTER {x: 1, y: 2}
- &LEFT {x: 0, y: 2}
- &BIG {r: 10}
- &SMALL {r: 1}
# All the following maps are equal:
# Explicit keys
- x: 1
  y: 2
  r: 10
  label: center/big
# Merge one map
- <<: *CENTER
  r: 10
  label: center/big
# Merge multiple maps
- <<: [*CENTER, *BIG]
  label: center/big
# Override
- <<: [*BIG, *LEFT, *SMALL]
  x: 1
  label: center/big
"""


def func():
    yaml = YAML()
    data = yaml.load(inp)
    print(data)
    print(f"1、[]方法为:{data[7]['y']}")
    print(f"2、.get()方法为:{data[7].get('y')}")
    assert data[7]['y'] == 2


if __name__ == "__main__":
    func()
  • 结果是:
[ordereddict([('x', 1), ('y', 2)]), 
ordereddict([('x', 0), ('y', 2)]), 
ordereddict([('r', 10)]), 
ordereddict([('r', 1)]), 
ordereddict([('x', 1), ('y', 2), ('r', 10), ('label', 'center/big')]), ordereddict([('r', 10), ('label', 'center/big'), ('x', 1), ('y', 2)]), ordereddict([('label', 'center/big'), ('x', 1), ('y', 2), ('r', 10)]), ordereddict([('x', 1), ('label', 'center/big'), ('r', 10), ('y', 2)])]
[]方法为:2
.get()方法为:2

7 使用insert()方法插入内容

import sys
from ruamel.yaml import YAML

yaml_str = """\
first_name: Art
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...
"""

yaml = YAML()
data = yaml.load(yaml_str)
data.insert(1, 'last name', 'Vandelay', comment="new key")
yaml.dump(data, sys.stdout)
  • 结果为以下,可以发现插入了数据last name: Vandelay
first_name: Art
last name: Vandelay    # new key
occupation: Architect  # This is an occupation comment
about: Art Vandelay is a fictional character that George invents...

8 使用yaml.indent()更改默认缩进

  • 默认情况下,ruamel.yaml以块样式缩进两个位置,用于映射和序列;
  • 对于序列,缩进计算到标量的开头,破折号位于缩进的“空格”的第一个位置;
  • 可以通过例如使用yaml.indent()来更改此默认缩进:
import sys
from ruamel.yaml import YAML

d = dict(a=dict(b=2),c=[3, 4])
yaml = YAML()
yaml.dump(d, sys.stdout)
print('0123456789')
yaml = YAML()
yaml.indent(mapping=4, sequence=6, offset=3)
yaml.dump(d, sys.stdout)
print('0123456789')
  • 结果为:
a:
  b: 2
c:
 - 3
 - 4
0123456789
a:
    b: 2
c:
 -  3
 -  4
0123456789

9 使用yaml.compact()隔行显示

  • 如果一个块序列或块映射是一个序列的元素,则默认情况下会显示紧凑的符号
  • 这意味着“父”序列的破折号与第一个元素resp位于同一行;
  • 子集合的第一个键/值对。
  • 如果希望其中一个或两个(序列内的序列,序列内的映射)从下一行开始,可以使用yaml.compact()
import sys
from ruamel.yaml import YAML

d = [dict(b=2), [3, 4]]
yaml = YAML()
yaml.dump(d, sys.stdout)
print('='*15)
yaml = YAML()
yaml.compact(seq_seq=False, seq_map=False)
yaml.dump(d, sys.stdout)
  • 结果是:
- b: 2
- - 3
  - 4
===============
-
  b: 2
-
  - 3
  - 4

10 同一数据使用三个转储,生成一个包含三个文档的流

import sys
from ruamel.yaml import YAML

data = {1: {1: [{1: 1, 2: 2}, {1: 1, 2: 2}], 2: 2}, 2: 42}

yaml = YAML()
yaml.explicit_start = True
yaml.dump(data, sys.stdout)
yaml.indent(sequence=4, offset=2)
yaml.dump(data, sys.stdout)


def sequence_indent_four(s):
    # this will fail on direclty nested lists: {1; [[2, 3], 4]}
    levels = []
    ret_val = ''
    for line in s.splitlines(True):
        ls = line.lstrip()
        indent = len(line) - len(ls)
        if ls.startswith('- '):
            if not levels or indent > levels[-1]:
                levels.append(indent)
            elif levels:
                if indent < levels[-1]:
                    levels = levels[:-1]
            # same -> do nothing
        else:
            if levels:
                if indent <= levels[-1]:
                    while levels and indent <= levels[-1]:
                        levels = levels[:-1]
        ret_val += '  ' * len(levels) + line
    return ret_val

yaml = YAML()
yaml.explicit_start = True
yaml.dump(data, sys.stdout, transform=sequence_indent_four)
  • 结果是:
---
1:
  1:
 - 1: 1
    2: 2
 - 1: 1
    2: 2
  2: 2
2: 42
---
1:
  1:
    - 1: 1
      2: 2
    - 1: 1
      2: 2
  2: 2
2: 42
---
1:
  1:
    - 1: 1
      2: 2
    - 1: 1
      2: 2
  2: 2
2: 42

11 将YAML输出作为字符串

  • 以下是新API的实现方法:
import sys
from ruamel.yaml import YAML
from ruamel.yaml.compat import StringIO

class MyYAML(YAML):
    def dump(self, data, stream=None, **kw):
        inefficient = False
        if stream is None:
            inefficient = True
            stream = StringIO()
        YAML.dump(self, data, stream, **kw)
        if inefficient:
            return stream.getvalue()

yaml = MyYAML()   # or typ='safe'/'unsafe' etc
print(yaml.dump(dict(a=1, b=2)))
  • 旧API是如下:
yaml.dump((dict(a=1, b=2)), sys.stdout)
print()  # or sys.stdout.write('\n')
目录
相关文章
|
2月前
|
开发者 Python
如何在Python中管理模块和包的依赖关系?
在实际开发中,通常会结合多种方法来管理模块和包的依赖关系,以确保项目的顺利进行和可维护性。同时,要及时更新和解决依赖冲突等问题,以保证代码的稳定性和可靠性
72 4
|
1月前
|
Python
Python Internet 模块
Python Internet 模块。
124 74
|
2月前
|
算法 数据安全/隐私保护 开发者
马特赛特旋转算法:Python的随机模块背后的力量
马特赛特旋转算法是Python `random`模块的核心,由松本真和西村拓士于1997年提出。它基于线性反馈移位寄存器,具有超长周期和高维均匀性,适用于模拟、密码学等领域。Python中通过设置种子值初始化状态数组,经状态更新和输出提取生成随机数,代码简单高效。
130 63
|
2月前
|
测试技术 Python
手动解决Python模块和包依赖冲突的具体步骤是什么?
需要注意的是,手动解决依赖冲突可能需要一定的时间和经验,并且需要谨慎操作,避免引入新的问题。在实际操作中,还可以结合使用其他方法,如虚拟环境等,来更好地管理和解决依赖冲突😉。
|
14天前
|
Python
[oeasy]python057_如何删除print函数_dunder_builtins_系统内建模块
本文介绍了如何删除Python中的`print`函数,并探讨了系统内建模块`__builtins__`的作用。主要内容包括: 1. **回忆上次内容**:上次提到使用下划线避免命名冲突。 2. **双下划线变量**:解释了双下划线(如`__name__`、`__doc__`、`__builtins__`)是系统定义的标识符,具有特殊含义。
26 3
|
2月前
|
持续交付 Python
如何在Python中自动解决模块和包的依赖冲突?
完全自动解决所有依赖冲突可能并不总是可行,特别是在复杂的项目中。有时候仍然需要人工干预和判断。自动解决的方法主要是提供辅助和便捷,但不能完全替代人工的分析和决策😉。
|
2月前
|
Python
Python的模块和包
总之,模块和包是 Python 编程中非常重要的概念,掌握它们可以帮助我们更好地组织和管理代码,提高开发效率和代码质量
56 5
|
2月前
|
数据可视化 Python
如何在Python中解决模块和包的依赖冲突?
解决模块和包的依赖冲突需要综合运用多种方法,并且需要团队成员的共同努力和协作。通过合理的管理和解决冲突,可以提高项目的稳定性和可扩展性
|
2月前
|
JavaScript 前端开发 Python
python中的OS模块的基本使用
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。博客分享前端技术及全栈开发经验,持续更新中,期待您的关注和支持!🎉🎉🎉
47 0
|
2月前
|
JavaScript 前端开发 Python
python中的platform模块的基本使用
欢迎来到瑞雨溪的博客,一名热爱JavaScript与Vue的大一学生。博客分享前端技术,助你成长。关注我,持续更新中!🎉🎉🎉
35 0