我想让PyYAML的加载器将映射(和有序映射)加载到Python2.7+OrderedDict类型中,而不是使用vanilladict及其当前使用的对列表
最好的方法是什么
Python>;=3.6
在Python3.6+中,似乎默认情况下保留了dict加载顺序,而没有特殊的字典类型。另一方面,默认的转储程序按键对字典进行排序。从pyyaml 5.1开始,您可以通过传递sort\u keys=False来关闭此功能:
a=dict(zip(“未排序的”、“未排序的”))
s=yaml.safe\u转储(a,排序\u键=False)
b=yaml.安全荷载
断言列表(a.keys())==列表(b.keys())#True
由于pypy中已经使用了一段时间的新dict实现,这可以正常工作。虽然仍在考虑CPython 3.6中的实施细节,但;DICT的插入顺序保持特性已被宣布为Python语言规范的正式部分;从3.7+开始,请参见Python 3.7的新增功能
请注意,这仍然没有从PyYAML方面进行记录,所以您不应该将其用于安全关键应用程序
原始答案(与所有已知版本兼容)
我喜欢@James的简单解决方案。但是,它更改了默认的全局yaml.Loader类,这可能会导致麻烦的副作用。尤其是在编写库代码时,这是一个坏主意。此外,它不能直接与yaml.safe\u load()配合使用
幸运的是,解决方案可以不费吹灰之力地改进:
导入yaml
从集合导入订单
def ordered_load(流,加载程序=yaml.SafeLoader,对象对\u hook=OrderedDict):
类OrderedLoader(装入器):
通过
def构造映射(加载器、节点):
loader.flant_映射(节点)
返回对象\u对\u钩子(装入器.构造\u对(节点))
OrderedLoader.add\u构造函数(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_标记,
构造(U映射)
返回yaml.load(流、OrderedLoader)
#用法示例:
有序装载(流、yaml.SafeLoader)
对于序列化,可以使用以下函数:
def ordered\u dump(数据,流=None,Dumper=yaml.SafeDumper,**kwds):
类OrderedDumper(转储程序):
通过
def_dict_representer(转储程序,数据):
返回dumper.representation\u映射(
yaml.resolver.BaseResolver.DEFAULT_MAPPING_标记,
data.items())
OrderedDumper.add_representer(OrderedDict,_dict_representer)
返回yaml.dump(数据、流、OrderedDumper,**kwds)
#用法:
有序转储(数据,转储程序=yaml.SafeDumper)
在每种情况下,您还可以将自定义子类设置为全局的,这样就不必在每次调用时重新创建它们