【问题标题】:Dump object into yaml without quotes将对象转储到 yaml 中,不带引号
【发布时间】:2020-09-01 12:20:27
【问题描述】:

我有一些对象想要转换为 yaml,唯一的事情是我需要能够将“!anything”不带引号放入其中。

当我尝试使用 pyyaml 时,我的 yaml 文件中出现了“!anything”。

我已经尝试过使用 ruamel.yaml PreservedScalarString 和 LiteralScalarString。它有点工作,但不是我需要工作的方式。问题是我最终得到的 yaml 看起来像这样:

10.1.1.16:
            text: '1470814.27'
            confidence: |-
              !anything

但我不需要这个 |- 符号。

我的目标是得到这样的 yaml:

10.1.1.16:
            text: '1470814.27'
            confidence: !anything

有什么想法可以实现吗?

【问题讨论】:

  • 在 YAML 中,!anything(以及通常以! 开头的任何内容)是一个标签(即不是内容)。如果您希望 !anything 被视为内容,您必须使用单引号或双引号或块标量(|->-)。
  • @flyx 如果我希望能够转储标签该怎么办?问题是我需要以某种方式从我的 python 代码中编写它

标签: python yaml dump pyyaml ruamel.yaml


【解决方案1】:

要转储自定义标签,您需要定义一个类型并为该类型注册一个表示器。以下是标量的方法:

import yaml

class MyTag:
  def __init__(self, content):
    self.content = content

  def __repr__(self):
    return self.content

  def __str__(self):
    return self.content

def mytag_dumper(dumper, data):
  return dumper.represent_scalar("!anything", data.content)

yaml.add_representer(MyTag, mytag_dumper)

print(yaml.dump({"10.1.1.16": {
    "text": "1470814.27",
    "confidence": MyTag("")}}))

这会发出

10.1.1.16:
  confidence: !anything ''
  text: '1470814.27'

注意标记后面的'',它是标记的标量(不,你无法摆脱它)。您也可以标记集合,但您需要相应地使用 represent_sequencerepresent_mapping

【讨论】:

  • 与直接流式传输到 sys.stdout 相比,首先流式传输到 StringIO 缓冲区然后打印该缓冲区的内容是不必要的低效(无论是在内存消耗方面还是在时间上)。所以你应该始终使用yaml.dump(data, sys.stdout) 而不是print(yaml.dump(data))
【解决方案2】:

与@flix 注释相反,在 YAML 中,您不需要在标签后面加上单引号或双引号(或块标量)。您可以尝试使用 Oren Ben-Kiki 的 reference parser(以编程方式从 YAML 规范派生)来确认您的预期输出是有效的 YAML。

空内容通常在 Python 中加载为 None(由过时的 PyYAML 和 ruamel.yaml 加载)。标记为空的内容当然只能表示特定实例的存在,没有任何值的指示。

ruamel.yaml 可以完美地往返您的预期输出:

import sys
from ruamel.yaml import YAML

yaml_str = """\
10.1.1.16:
  text: '1470814.27'
  confidence: !anything
"""

yaml = YAML()
data = yaml.load(yaml_str)

yaml.dump(data, sys.stdout)

给予:

10.1.1.16:
  text: '1470814.27'
  confidence: !anything

您可以生成一个只转储没有值的标记的对象(就像解析器所做的那样),但是如果您不想深入了解细节,您可以加载标记的对象并将其添加到您的数据结构:

import sys
import ruamel.yaml


yaml = ruamel.yaml.YAML()


def tagged_empty_scalar(tag):
   return yaml.load('!' + tag)

data = {'10.1.1.16': dict(text='1470814.27', confidence=tagged_empty_scalar('anything'))}

yaml.dump(data, sys.stdout)

你可以在 PyYAML 中得到完全相同的结果,但不带引号,但这更复杂。

【讨论】:

    猜你喜欢
    • 2019-01-16
    • 2021-05-13
    • 2020-11-16
    • 2014-06-11
    • 2018-11-04
    • 1970-01-01
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多