【问题标题】:Python dictionaries into yaml documents using PyYaml使用 PyYaml 将 Python 字典转换为 yaml 文档
【发布时间】: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 中缺少功能,这是克服它的最优雅的方法。

【问题讨论】:

    标签: python yaml 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 的次数越多,我就意识到它是多么的蹩脚。
      • 我添加了一些代码来展示如何以编程方式定义类。
      猜你喜欢
      • 2019-03-16
      • 2018-12-19
      • 2011-10-12
      • 2011-03-15
      • 2020-11-12
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 2021-07-17
      相关资源
      最近更新 更多