PyYAML 转储格式 [英] PyYAML dump format

查看:47
本文介绍了PyYAML 转储格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道在 SO 上有一些关于此的问题,但我找不到我要找的东西.

我正在使用 pyyaml 来读取 (.load()) 一个 .yml 文件,修改或者增加一个key,然后再写一遍(.dump()).问题是我想保留转储后的文件格式,但它发生了变化.

例如,我编辑键 en.test.index.few"Bye" 而不是 "Hello"

Python:

with open(path, 'r', encoding = "utf-8") 作为 yaml_file:self.dict = pyyaml.load(yaml_file)

然后,更改密钥后:

with open(path, 'w', encoding = "utf-8") 作为 yaml_file:dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None)yaml_file.write( 转储 )

Yaml:

之前:

en:测试:新:再见"指数:几个:你好"另一个测试:某事"

之后:

en:另一个测试:某事测试:指数:几个:你好新:再见

有没有办法保持相同的格式?,例如 qoutes 和 order.我是否为此使用了错误的工具?

我知道原始文件可能不完全正确,但我无法控制它(它是 Ruby on Rails i18n 文件).

非常感谢.

解决方案

下面,使用 ruamel.yaml 代替.

ruamel.yaml积极维护.与 PyYAML 不同,ruamel.yaml 支持:

  • YAML <= 1.2. PyYAML 仅支持 YAML <= 1.1.这很重要,因为 YAML 1.2 有意 在一些边缘情况下破坏了与 YAML 1.1 的向后兼容性.这通常是一件坏事.在这种情况下,这使 YAML 1.2 成为 JSON 的严格超集.由于 YAML 1.1 不是 JSON 的严格超集,因此这是一件好事.
  • 往返保存. 当调用 yaml.dump() 来转储之前调用 yaml.load() 加载的字典时:
    • PyYAML 天真地忽略所有输入格式——包括注释、排序、引用和空格.像很多数字垃圾一样被丢弃到最近的可用比特桶中.
    • ruamel.yaml 巧妙地尊重所有 输入格式.一切.整个风格的辣酱玉米饼馅.整个文学社邦.全部.

库迁移

在现有应用程序中从 PyYAML 切换到 ruamel.yaml 通常就像将库导入更改为一样简单:

from ruamel import yaml

之所以有效,是因为 ruamel.yaml 是符合 PyYAML API 的 PyYAML 分支.

不需要其他更改.yaml.load()yaml.dump() 函数应该继续按预期运行.

往返保存及其能为您做什么

为了与 PyYaml 向后兼容,yaml.load()yaml.dump() 函数在默认情况下执行往返保存.为此,明确传递:

  • yaml.load() 的可选 Loader=ruamel.yaml.RoundTripLoader 关键字参数.
  • yaml.dump() 的可选 Dumper=ruamel.yaml.RoundTripDumper 关键字参数.

一个善意借用"的例子来自 ruamel.yaml 文档:

import ruamel.yamlinp =""\# 例子名称:# 又一个伟大的地狱公爵.他没那么坏,真的.家族:TheMighty给定:阿什塔罗斯"代码 = ruamel.yaml.load(inp, Loader=ruamel.yaml.RoundTripLoader)code['name']['given'] = 'Astarte' # 哦不,你没有.打印(ruamel.yaml.dump(代码,Dumper=ruamel.yaml.RoundTripDumper),end='')

大功告成.评论、排序、引用和空格现在将完好无损.

I know there are a few questions about this on SO, but I couldn't find what I was looking for.

I'm using pyyaml to read (.load()) a .yml file, modify or add a key, and then write it (.dump()) again. The problem is that I want to keep the file format post-dump, but it changes.

For example, I edit the key en.test.index.few to say "Bye" instead of "Hello"

Python:

with open(path, 'r', encoding = "utf-8") as yaml_file:
    self.dict = pyyaml.load(yaml_file)

Then, afther changing the key:

with open(path, 'w', encoding = "utf-8") as yaml_file:
    dump = pyyaml.dump(self.dict, default_flow_style = False, allow_unicode = True, encoding = None)
    yaml_file.write( dump )

Yaml:

Before:

en:
  test:
    new: "Bye"
    index:
      few: "Hello"
  anothertest: "Something"

After:

en:
  anothertest: Something
  test:
    index:
      few: Hello
    new: Bye

Is there a way to keep the same format?, for example the qoutes and order. Am I using the wrong tool for this?

I know maybe the original file it's not entirely correct, but I have no control over it (it's a Ruby on Rails i18n file).

Thank you very much.

解决方案

Below, ruamel.yaml is used instead.

ruamel.yaml is actively maintained. Unlike PyYAML, ruamel.yaml supports:

  • YAML <= 1.2. PyYAML only supports YAML <= 1.1. This is vital, as YAML 1.2 intentionally breaks backward compatibility with YAML 1.1 in several edge cases. This would usually be a bad thing. In this case, this renders YAML 1.2 a strict superset of JSON. Since YAML 1.1 is not a strict superset of JSON, this is a good thing.
  • Roundtrip preservation. When calling yaml.dump() to dump a dictionary loaded by a prior call to yaml.load():
    • PyYAML naively ignores all input formatting – including comments, ordering, quoting, and whitespace. Discarded like so much digital refuse into the nearest available bit bucket.
    • ruamel.yaml cleverly respects all input formatting. Everything. The whole stylistic enchilada. The entire literary shebang. All.

Library Migration

Switching from PyYAML to ruamel.yaml in existing applications is typically as simple as changing the library import to:

from ruamel import yaml

This works because ruamel.yaml is a PyYAML fork that conforms to the PyYAML API.

No other changes should be needed. The yaml.load() and yaml.dump() functions should continue to behave as expected.

Roundtrip Preservation and What It Can Do for You

For backward compatibility with PyYaml, the yaml.load() and yaml.dump() functions do not perform roundtrip preservation by default. To do so, explicitly pass:

  • The optional Loader=ruamel.yaml.RoundTripLoader keyword parameter to yaml.load().
  • The optional Dumper=ruamel.yaml.RoundTripDumper keyword parameter to yaml.dump().

An example kindly "borrowed" from ruamel.yaml documentation:

import ruamel.yaml

inp = """\
# example
name:
  # Yet another Great Duke of Hell. He's not so bad, really.
  family: TheMighty
  given: Ashtaroth
"""

code = ruamel.yaml.load(inp, Loader=ruamel.yaml.RoundTripLoader)
code['name']['given'] = 'Astarte'  # Oh no you didn't.

print(ruamel.yaml.dump(code, Dumper=ruamel.yaml.RoundTripDumper), end='')

It is done. Comments, ordering, quoting, and whitespace will now be preserved intact.

这篇关于PyYAML 转储格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆