我有这个YAML文件:
pb:
{EF:{16, 19}, EH:{16, 19}}
当我应用flattendict
Python函数时,我得到了
{('pb', 'EF', 16): None,
('pb', 'EF', 19): None,
('pb', 'EH', 16): None,
('pb', 'EH', 19): None}
我按如下所示搜索YAML文件的语法,以获得相同的结果(我想将我的YAML节点数据作为因数)
pb:
{EF, EH}, {16, 19}}
你有个主意吗?
这是我的python flattendict函数
#!/usr/bin/env python
#encoding: UTF-8
import codecs
import sys
import yaml
import pprint
import collections
from collections import Mapping
from itertools import chain
from operator import add
_FLAG_FIRST = object()
def flattenDict(d, join=add, lift=lambda x:x):
results = []
def visit(subdict, results, partialKey):
for k,v in subdict.items():
newKey = lift(k) if partialKey==_FLAG_FIRST else join(partialKey,lift(k))
if isinstance(v,Mapping):
visit(v, results, newKey)
else:
results.append((newKey,v))
visit(d, results, _FLAG_FIRST)
return results
testdata = yaml.safe_load(open('data.yaml', 'r'))
from pprint import pprint as pp
result = flattenDict(testdata, lift=lambda x:(x,))
pp(dict(result))
答案 0 :(得分:0)
在YAML中,即使使用简单的键(例如,没有?
,标记),您也可以具有复杂的流节点。 YAML 1.2和YAML 1.1都是如此。这意味着:
{a: 1, b: 2}: mapping
[1, 2, a]: sequence
是正确的YAML。
问题在于,映射通常作为Python dict
和序列作为Python list
加载,二者都是可变的,不能被散列,并且不允许作为Python的键dict
(尝试执行python -c "{{'a': 1}: 2}"
)。
PyYAML(支持YAML 1.1)错误。
由于Python具有list
形式的不可变tuple
,因此我决定通过在ruamel.yaml
中将它们构造为元组来实现Python中序列键的加载(它支持YAML 1.2和YAML 1.1)。所以下面的工作:
import sys
import ruamel.yaml
from pprint import pprint as pp
yaml_str = """\
[pb, EF, 16]:
[pb, EF, 19]:
[pb, EH, 16]:
[pb, EH, 19]:
"""
yaml = ruamel.yaml.YAML(typ='rt')
# yaml.indent(mapping=4, sequence=4, offset=2)
# yaml.preserve_quotes = True
data = yaml.load(yaml_str)
pp(data)
print('---------')
yaml.dump(data, sys.stdout)
打印:
{('pb', 'EF', 16): None,
('pb', 'EF', 19): None,
('pb', 'EH', 16): None,
('pb', 'EH', 19): None}
---------
[pb, EF, 16]:
[pb, EF, 19]:
[pb, EH, 16]:
[pb, EH, 19]:
如果您尝试在PyYAML中加载上述YAML,则会引发异常:
found unhashable key
in "<unicode string>", line 1, column 1:
[pb, EF, 16]:
注意:
如果您不想往返,请使用typ="safe"
,它使用速度更快的C加载程序,该C加载程序还可以处理按顺序排列的键,但是它不那么聪明将其转储回去,从而产生标记为?
的显式密钥。
用于Python的proposal for a frozendict
未被接受,因此,即使在dict
的标准库中也没有等效项,对于{{ 1}}和tuple
不支持将映射作为开箱即用的键。如果您有这样的问题,当然可以将其添加到list
的构造函数中。
尽管Python中有一个frozenset
,而YAML中有一个集合,但是ruamel.yaml
当前不不接受以下内容作为输入:< / p>
ruamel.yaml
也许无需多说:您不能以编程方式更改此类键的元素,而无需删除并重新添加键值对。