繁体   English   中英

YAML output python 的格式

[英]YAML output format of python

我用PyYaml来 output 一个YAML文件。 但它重新订购我的物品。 喜欢关注

>>> yaml.dump({'3':5, '1':3})
"{'1': 3, '3': 5}\n"

我想得到"{'3': 5, '1': 3}\n" 我可以做那件事吗

附言 我试过collections.OrderedDict 它的 output 不好。 喜欢关注

>>> a= collections.OrderedDict()
>>> a['3']=1
>>> a['1']=2
>>> a['5']=2
>>> yaml.dump(a)
"!!python/object/apply:collections.OrderedDict\n- - ['3', 1]\n  - ['1', 2]\n  - ['5', 2]\n"

TL; DR:解决方案在两行中注释为“ LOOK HERE!”。 可能的,如果你接受的输出将是列表的列表来处理YAML作为你的程序中,并与存储的文件/文本排序类型的字典。

如果您不介意!! python / ordered_dict或!! omap这样令人讨厌的显式类型,那么您也可以采用这种方式。 我的投票投给!! omap,但是我不确定有多少工具/库支持它(我敢肯定,支持!! python / ordered_dict的工具会更少)。 最终,您要处理两个独立的数据集:dict本身和定义键顺序的元数据。

(在YAML中有半魔术的方法可以强制有序的dict到处没有!! python / ordered_dict或!! omap混乱,但是它们很脆弱,与字典的定义相矛盾,并且可能随着基础YAML库的发展而中断。顺便说一下,这种情况对于JSON来说是相同的,因为YAML是JSON的超集,并且都不保证键的顺序-这意味着解决方法第一次打破了符合标准的工具/用户将文件弄乱的情况。)

这篇文章的其余部分是示例/验证代码,并解释了为什么这种方式。

from __future__ import print_function
import yaml

# Setting up some example data
d = {'name': 'A Project',
     'version': {'major': 1, 'minor': 4, 'patch': 2},
     'add-ons': ['foo', 'bar', 'baz']}

# LOOK HERE!
ordering = ['name', 'version', 'add-ons', 'papayas']
ordered_set = [[x, d[x]] for x in ordering if x in d.keys()]
# In the event you only care about a few keys,
# you can tack the unspecified ones onto the end
# Note that 'papayas' isn't a key. You can establish an ordering that
# includes optional keys by using 'if' as a guard in the list comprehension.

# Demonstration
things = {'unordered.yaml': d, 'ordered.yaml': ordered_set}
for k in things:
    f = open(k, 'w')
    f.write(yaml.dump(things[k], default_flow_style=False, allow_unicode=True))
    f.close()

# Let's check the result
output = []
for k in things:
    f = open(k, 'r')
    output.append(dict(yaml.load(f.read())))
    f.close()

# Should print 'OK'
if output[0] == output[1]:
    print('OK')
else:
    print('Something is wrong')

创建的文件如下所示:

ordered.yaml:

- - name
  - A Project
- - version
  - major: 1
    minor: 4
    patch: 2
- - add-ons
  - - foo
    - bar
    - baz

unordered.yaml:

add-ons:
- foo
- bar
- baz
name: A Project
version:
  major: 1
  minor: 4
  patch: 2

这不会像您希望的那样生成漂亮的YAML文档。 就是说,它可以将漂亮的YAML作为初始输入(是的!),并将脚本从不漂亮的,有序的YAML转换为漂亮的,仍然有序的,字典式的YAML脚本非常简单(我留给您练习) 。

如果您要保留的键排序,请将其写入有序列表/元组。 使用该列表生成列表的有序列表(不过,不是元组列表,因为在YAML中会得到!! python / tuple类型,这很糟糕)。 将其转储到YAML。 要按正常方式读回它,然后将该结构传递给dict(),您将返回到最初使用的原始字典。 如果您有一个嵌套结构要求保留其顺序,则可能必须递归地递减该结构(在代码中比在散文中解释要容易得多(这可能已经知道)。

在此示例中,我想让项目“名称”首先出现在文件中,然后是“版本”数字元素,然后是“附加组件”。 通常,当您调用dump()时,PyYAML会按字母数字顺序对字典键进行排序,但这是不可靠的,因为将来可能会发生变化,并且YAML标准中没有要求这样做的键,因此我无法保证使用其他YAML实用程序将以这种方式做事。 “附加组件”位于“名称”之前,因此我有订购问题。 因此,我定义了我的订单,然后打包一个有序列表列表,然后将其转储。

您要从本质上无序的订单中要求订单。 字典是一个哈希表,在内部专门按搜索速度排序。 该顺序是您不应该弄乱的,因为如果明天发现一种更快的实现字典的方式,则运行时需要在不破坏依赖于字典作为哈希表的有用抽象的每个人的代码的情况下实现它。

同样,YAML不是标记语言(毕竟,它最初是“ Yaml不是标记语言”的缩写),它是一种数据格式。 区别很重要。 一些数据是有序的,例如元组和列表。 有些则不是,例如成袋的键/值对(与哈希表稍有不同,但概念上相似)。

我使用这种解决方案的递归版本来保证跨不同YAML实现的YAML输出,而不是为了人类可读性,而是因为我在YAML中传递了大量数据,并且每条记录都必须用键进行签名,并且不确定的顺序可以防止使用字典/哈希时使用统一的签名。

YAML映射是无序的,Python字典也是如此。 读取文件并保持排序的官方方式是使用!!omap但是那些在PyYAML中被转换为元组,并且不像dict / ordereddict / OrderedDict那样容易更新。

如果您已经有一个读入并更新的yaml文件,则可以使用我的ruamel.yaml库,该库在来回模式下按ordersdict读取映射,并将其写为普通映射(它还会保留注释)。

给出了用法示例 ,作为对另一个问题的解答。

I might be a little late to the party but using the function add_representer of the yaml package seems to resolve the problem.I just added the yaml.add_representer(collections.OrderedDict, Representer.represent_dict) before my yaml.dump and my yaml does not不再有上述格式警告:

import collections
import yaml

l= collections.OrderedDict()
l['hax']=45
l['ko']=[4,5]
l['ax']="less"

yaml.dump(l)
#output:'!!python/object/apply:collections.OrderedDict\n- - - hax\n    - 45\n  - - ko\n    - - 4\n      - 5\n  - - ax\n    - less\n'

#adding a representer for Ordered Dictionaries
from yaml.representer import Representer
yaml.add_representer(collections.OrderedDict, Representer.represent_dict)

yaml.dump(l)
#output'ax: less\nhax: 45\nko:\n- 4\n- 5\n'

如果有帮助,请告诉我。

另一种解决方案可能也是使用oyaml而不是 pyyaml,正如它在这篇文章中所建议的那样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM