将对象转储到不带引号的 yaml 中
Dump object into yaml without quotes
我有一些我想变成 yaml 的对象,唯一的问题是我需要能够将不带引号的“!任何东西”放入其中。
当我尝试使用 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
有什么办法可以实现吗?
要转储自定义标签,您需要定义一个类型并为该类型注册一个代表。以下是对标量的处理方法:
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_sequence
或 represent_mapping
。
与@flix 评论相反,在 YAML 中,您不需要在标签后加上单引号或双引号(或块标量)。您可以尝试 Oren Ben-Kiki 的 reference parser(以编程方式从 YAML 规范派生)来确认您的预期输出是有效的 YAML。
空内容通常在 Python 中加载为 None
(由过时的 PyYAML 和 ruamel.yaml 加载)。标记为空的内容当然可以只表示特定实例的存在,而不表示任何值。
ruamel.yaml 可以很好地 round-trip 你的预期输出:
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 中获得完全相同的结果,但不带引号,但更复杂。
我有一些我想变成 yaml 的对象,唯一的问题是我需要能够将不带引号的“!任何东西”放入其中。
当我尝试使用 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
有什么办法可以实现吗?
要转储自定义标签,您需要定义一个类型并为该类型注册一个代表。以下是对标量的处理方法:
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_sequence
或 represent_mapping
。
与@flix 评论相反,在 YAML 中,您不需要在标签后加上单引号或双引号(或块标量)。您可以尝试 Oren Ben-Kiki 的 reference parser(以编程方式从 YAML 规范派生)来确认您的预期输出是有效的 YAML。
空内容通常在 Python 中加载为 None
(由过时的 PyYAML 和 ruamel.yaml 加载)。标记为空的内容当然可以只表示特定实例的存在,而不表示任何值。
ruamel.yaml 可以很好地 round-trip 你的预期输出:
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 中获得完全相同的结果,但不带引号,但更复杂。