使用 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 文档的主要内容,如果未能解决你的问题,请参考以下文章
如何在python中使用pandas将字典列表转换为数据框[重复]