PyYAML转储表单

2024-04-25 04:47:37 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道有一些问题,所以,但我找不到我在寻找什么。

我正在使用pyyaml读取(.load())一个.yml文件,修改或添加一个密钥,然后再次写入(.dump())。问题是我想在转储后保留文件格式,但它会改变。

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

Python:

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

然后,在更换钥匙之后:

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 )

山药:

之前:

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

之后:

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

有没有办法保持同样的格式?,例如qoutes和order。我用错工具了吗?

我知道原始文件可能不完全正确,但我无法控制它(它是一个rubyonrailsi18n文件)。

非常感谢。


Tags: 文件testyamlhelloindexwithloadopen
3条回答

在我的例子中,如果值包含{},则需要",否则什么都不需要。例如:

 en:
   key1: value is 1
   key2: 'value is {1}'

要执行此操作,请从模块PyYaml中的文件representer.py复制函数represent_str(),如果字符串包含{},请使用另一种样式:

def represent_str(self, data):
    tag = None
    style = None
    # Add these two lines:
    if '{' in data or '}' in data:
        style = '"'
    try:
        data = unicode(data, 'ascii')
        tag = u'tag:yaml.org,2002:str'
    except UnicodeDecodeError:
        try:
            data = unicode(data, 'utf-8')
            tag = u'tag:yaml.org,2002:str'
        except UnicodeDecodeError:
            data = data.encode('base64')
            tag = u'tag:yaml.org,2002:binary'
            style = '|'
    return self.represent_scalar(tag, data, style=style)

要在代码中使用它:

import yaml

def represent_str(self, data):
  ...

yaml.add_representer(str, represent_str)

在这种情况下,键和值之间没有差别,这对我来说就足够了。如果您想要键和值的不同样式,请对函数represent_mapping执行相同的操作

改用^{}

图书馆打架!两个图书馆的故事

PyYAML是effectively dead,已经有好几年了。更复杂的是,位于http://pyyaml.org的官方项目最近似乎已经被拆除。此站点托管了PyYAML问题跟踪程序、文档和下载。在写这篇文章的时候,一切都消失了。这简直是灾难。欢迎来到开源的新一天。

ruamel.yamlactively maintained。与PyYAML不同,ruamel.yaml支持:

  • YAML<;=1.2。PyYAML只支持YAML<;=1.1。这是至关重要的,因为YAML 1.2在一些边缘情况下有意使用yaml1.1 breaks backward compatibility。这通常是件坏事。在本例中,这使YAML 1.2成为JSON的严格超集。由于YAML 1.1是JSON的严格超集,所以这是一件好事。
  • 往返保存。调用yaml.dump()转储先前调用yaml.load()加载的字典时:
    • PyYAML天真地忽略了所有输入格式,包括注释、排序、引用和空白。像这么多数字垃圾一样丢弃到最近的可用位桶中。
    • ruamel.yaml巧妙地尊重所有输入格式。一切。整个风格。整个文学史。全部。

库迁移:代码撕裂的痕迹

由于ruamel.yaml是PyYAML fork,因此符合PyYAML API,在现有应用程序中从PyYAML切换到ruamel.yaml通常与替换以下所有实例一样简单:

# This imports PyYAML. Stop doing this.
import yaml

……用这个:

# This imports "ruamel.yaml". Always do this.
from ruamel import yaml

就这样。

不需要进行其他更改。yaml.load()yaml.dump()函数应继续按预期工作,其额外好处是现在支持YAML 1.2并积极接收错误修复。

往返保存和它能为你做什么

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

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

^{} 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='')

完成。注释、排序、引用和空白现在将保持原样。

tl;博士

始终使用ruamel.yaml。千万不要用派亚姆。ruamel.yaml生命。皮亚姆是一具腐烂的恶臭尸体,尸体在皮皮的模制沙坑里腐烂。

万岁。

首先

以下代码用于表示字典数据:

mapping = list(mapping.items())
    try:
        mapping = sorted(mapping)
    except TypeError:
        pass

这就是为什么订单会改变

有关标量类型的显示方式(是否带双引号)的信息在读取时丢失(这是库的主要方法)

摘要

您可以基于“Dumper”创建自己的类,并重载方法“represent_mapping”以更改字典的显示方式

为了保存有关标量双引号的信息,您还必须基于“Loader”创建自己的类,但我担心这会影响和其他类,并且会很难做到

相关问题 更多 >