使用 PyYaml 将 Python 字典转换为 yaml 文档

Posted

技术标签:

【中文标题】使用 PyYaml 将 Python 字典转换为 yaml 文档【英文标题】:Python dictionaries into yaml documents using PyYaml 【发布时间】:2012-12-16 05:32:55 【问题描述】:

我有两个 python 字典,我想将它们写入一个 yaml 文件,其中包含两个文档:

definitions = "one" : 1, "two" : 2, "three" : 3
actions = "run" : "yes", "print" : "no", "report" : "maybe"

yaml 文件应如下所示:

--- !define
one: 1
two: 2
three: 3

-- !action
run: yes
print: no
report: maybe
...

使用 PyYaml 我没有找到明确的方法来做到这一点。我确信有一个简单的方法,但是深入研究 PyYaml 文档,只会让我感到困惑。我需要翻斗车、发射器还是什么?这些类型中的每一种产生什么类型的输出? Yaml 文本? yaml 节点? YAML 对象?无论如何,我将不胜感激。


根据以下 unutbu 的回答,这是我能想到的最简洁的版本:

DeriveYAMLObjectWithTag 是一个创建新类的函数,从 YAMLObject 派生并带有所需的标签:

def DeriveYAMLObjectWithTag(tag):
    def init_DeriveYAMLObjectWithTag(self, **kwargs):
        """ __init__ for the new class """
        self.__dict__.update(kwargs)

    new_class = type('YAMLObjectWithTag_'+tag,
                    (yaml.YAMLObject,),
                    'yaml_tag' : '!n'.format(n = tag),
                    '__init__' :  init_DeriveYAMLObjectWithTag)
    return new_class

这里是如何使用 DeriveYAMLObjectWithTag 来获取所需的 Yaml:

definitions = "one" : 1, "two" : 2, "three" : 3, "four" : 4
actions = "run" : "yes", "print" : "no", "report" : "maybe"
namespace = [DeriveYAMLObjectWithTag('define')(**definitions),
             DeriveYAMLObjectWithTag('action')(**actions)]

text = yaml.dump_all(namespace,
                     default_flow_style = False,
                     explicit_start = True)

感谢所有回答的人。我似乎在 PyYaml 中缺少功能,这是克服它的最优雅的方法。

【问题讨论】:

【参考方案1】:

好吧,我仍在研究自动 cmets(无法立即找到相关文档),但这应该可以解决问题:

import yaml

definitions = "one" : 1, "two" : 2, "three" : 3
actions = "run" : "yes", "print" : "no", "report" : "maybe"

output = yaml.dump(actions, default_flow_style=False, explicit_start=True)
output += yaml.dump(definitions, default_flow_style=False, explicit_start=True)

print output

请注意,字典是无序的,因此无法保证生成的 YAML 的顺序。如果您想在家中订购 - 请查看OrderedDict。

【讨论】:

【参考方案2】:

怎么样:

class Bunch(yaml.YAMLObject):
    yaml_tag = u'!Bunch'
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
    def __repr__(self):
        return 'c(a)'.format(
            c = self.__class__.__name__,
            a = ', '.join(
                ['='.join(map(str,item)) for item in self.__dict__.items()]))
tag_names = ['define', 'action']
namespace = 
for name in tag_names:
    namespace[name] = type(name, (Bunch,), 'yaml_tag':u'!n'.format(n = name))

definitions = "one" : 1, "two" : 2, "three" : 3
actions = "run" : "yes", "print" : "no", "report" : "maybe"
text = yaml.dump_all([namespace['define'](**definitions),
                      namespace['action'](**actions)],
                     default_flow_style = False,
                     explicit_start = True)
print(text)

产生

--- !define
one: 1
three: 3
two: 2
--- !action
print: 'no'
report: maybe
run: 'yes'

并将 YAML 加载回 Python 对象:

for item in  yaml.load_all(text):
    print(item)
    # define(one=1, three=3, two=2)
    # action(print=no, report=maybe, run=yes)

YAMLObject 的子类用于创建application-specific tags.

【讨论】:

@favoretti:确实是将输出划分为文档的正是explicit_start=True。在 PyYAMLDocumentation 中根本没有记录explicit_start,仅在示例中提及。 为每个特定标签声明一个类的想法可行,但不适用于有许多此类标签的大型项目。我使用 PyYaml 的次数越多,我就意识到它是多么的蹩脚。 我添加了一些代码来展示如何以编程方式定义类。

以上是关于使用 PyYaml 将 Python 字典转换为 yaml 文档的主要内容,如果未能解决你的问题,请参考以下文章

pyyaml “有序”解析/生成yaml

python中如何将字符串转换为字典

将字典转换为字节并再次返回python? [复制]

如何在python中使用pandas将字典列表转换为数据框[重复]

如何加载 pyYAML 文件并使用属性而不是使用字典表示法访问它?

Python的PyYAML模块详解