我目前对PyYAML有点困惑。我在我的Windows和Linux系统上安装了3.12版,并且看到它在排序值时表现不同。
让我们看看这个示例YAML文件:
functions:
function_a:
value_1: 1
value_2: 1
value_3: 1
function_c:
value_1: 1
value_2: 1
value_3: 1
function_d:
value_1: 1
value_2: 1
value_4: 1
function_b:
value_1: 1
value_2: 1
value_3: 1
通过conf = yaml.load(fp)
照常加载YAML文件。
现在,这两个系统之间真正奇怪的是,当我尝试通过所有功能时,我在两个操作系统上都获得了不同的顺序。
在Windows上它将是:
import yaml
with open('myyamlfile.yml') as fp:
conf = yaml.load(fp)
for function in conf['functions']:
print(function)
function_a
function_c
function_d
function_b
在Linux上,它以有序的方式出现:
import yaml
with open('myyamlfile.yml') as fp:
conf = yaml.load(fp)
for function in conf['functions']:
print(function)
function_a
function_b
function_c
function_d
我真的不知道为什么。我在具有相同模块版本的两台机器上使用相同的代码。两台机器之间的唯一区别是操作系统和事实,在Windows上我使用的是3.6.5,而在Linux上我使用的是3.4.8。
有没有人暗示我为什么会这样?
答案 0 :(得分:1)
首先,YAML规范(PyYAML所基于的旧1.1以及较新的1.2规范(2009))都表明映射的键是无序的。因此,您不应该在加载后依赖订单。
然后在幕后,当然存在差异Python 3.6 dicts are ordered(在CPython实现中,在其他实现中以3.7开头),而Python 3.6之前的序列不是有序的。 PyYAML创建一个dict并按照从YAML文档中读取键的顺序填充它,因此3.6.5版本获得了键插入的顺序,3.4.8没有。
如果您需要两个版本的行为相同,我建议您明确对键进行排序:
for function in sort(conf['functions']):
如果您确实需要按照YAML文档中的顺序获取密钥,我建议您查看ruamel.yaml(免责声明:我是YAML 1.2兼容软件包的作者)并且确实如此。 e.g:
import pathlib
import ruamel.yaml
yaml = ruamel.yaml.YAML()
file_name = pathlib.Path('myfile.yaml')
conf = yaml.load(file_name)
for function in conf['functions']:
print(function)
它将在Python 3.6.5中为您提供Python 2.7到3.7中的输出。 (在ruamel.yaml中,yaml.load()
默认是安全的。)