python 如何强制ruamel.yaml的新API输出块样式而不是流样式?

bnl4lu3b  于 2023-06-04  发布在  Python
关注(0)|答案(1)|浏览(238)

我已经搜索过了,但找不到如何使用新的API强制ruamel.yaml以块的方式转储我的字典。
我的代码:

yaml = YAML(typ="safe")
    yaml.Representer = RoundTripRepresenter
    yaml.default_flow_style = False   ### also tried with None
    perfdata: dict[datetime, dict[int, float]] = {}
    performance_file = opts.mapdir / "performance.yaml"
    if performance_file.exists():
        make_backup(performance_file)
        with performance_file.open("rt") as fin:
            perfdata = yaml.load(fin)
    perfdata[datetime.now().astimezone()] = normalized_time_per_row
    with performance_file.open("wt") as fout:
        yaml.dump(perfdata, fout)

我试过了

  • default_flow_style=None放入.dump()调用中--错误意外的关键字参数
  • yaml.default_flow_style = None--仍然会导致流样式
  • yaml.default_flow_style = False--仍然会导致流样式

如何强制它以块样式发射?

nle07wnf

nle07wnf1#

你在混合事物,不清楚你从哪里得到的想法,你做他们的方式(这将是有趣的,知道你从哪里得到的例子)。仅仅更改YAML(typ="safe")示例上的表示器不会得到匹配的序列化器和发射器。你可以做的,但在这种情况下不需要的是有两个YAML()示例:

yaml_in = ruamel.yaml.YAML(typ='safe')
yaml_out = ruamel.yaml.YAML()
yaml_out.dump(yaml_in.load(path), sys.stdout)

这将使您在yaml_out中获得正确的序列化器和发射器,有效地删除注解并将文件内容转换为块样式。
如果你做了一个往返并保留注解,你根本不应该使用typ="safe",而应该使用默认值(或者使用显式的typ="rt",如果默认使用块样式。
如果您的performance.yaml文件只包含与例程一起输入的条目,则可以使用YAML(typ="safe")并在其上设置default_flow_style属性。

import sys
import datetime
from pathlib import Path
import ruamel.yaml

class UpdatePerformanceData:
    def __init__(self, path, typ=None):
        self._path = path
        self._yaml_typ = typ
        self._perfdata: [datetime, dict[int, float]] = {}

    @property
    def yaml(self):
        try:
            return self._yaml
        except AttributeError:
            pass
        if typ is None:
            self._yaml = ruamel.yaml.YAML()
        else:
            self._yaml = ruamel.yaml.YAML(typ=typ)
            self._yaml.default_flow_style = False
        return self._yaml

    def __call__(self, normalized_time_per_row):
        if len(self._perfdata) == 0 and self._path.exists():
            self._perfdata = self.yaml.load(self._path)
        data = self._perfdata
        data[datetime.datetime.now().astimezone()] = normalized_time_per_row
        self.yaml.dump(data, self._path)

path = Path('performance.yaml')

for typ in [None, 'safe']:
    upd = UpdatePerformanceData(path, typ=typ)

    upd({1: 42.0, 2: 3.14})
    upd({3: 17.8, 4: 2.718})
    sys.stdout.write(path.read_text())
    print('-------')
    path.unlink()

其给出:

2023-06-03 07:01:36.646197+02:00:
  1: 42.0
  2: 3.14
2023-06-03 07:01:36.648377+02:00:
  3: 17.8
  4: 2.718
-------
2023-06-03 07:01:36.648966+02:00:
  1: 42.0
  2: 3.14
2023-06-03 07:01:36.650003+02:00:
  3: 17.8
  4: 2.718
-------

所以在这两种情况下都得到block_style输出。如果您已经有(旧的)流样式条目,请使用typ="safe"。您可以在往返加载器/转储器上设置.default_flow_style,但它不会影响已加载数据,只会影响新添加的dicts和列表,对于typ='rt',流/块样式将保留,并且必须针对每个对象进行更改。
您应该开始使用pathlib.Path示例,它们可以防止您错误地打开/关闭文件。例如,yaml.dump()转储为UTF-8,这是一个二进制流。因此,使用"wt"会导致不必要的转换步骤。

相关问题