Python PyYAML在不同的操作系统中表现不同
我现在有点被Pyaml搞糊涂了。我在我的Windows和Linux系统上安装了3.12版,并且看到它在对值进行排序时的行为有所不同 让我们看一下这个示例YAML文件:Python PyYAML在不同的操作系统中表现不同,python,pyyaml,Python,Pyyaml,我现在有点被Pyaml搞糊涂了。我在我的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 funct
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.loadfp加载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
有人能告诉我为什么会发生这种情况吗?首先是YAML规范,PyYAML所基于的旧1.1规范和新的1.2规范2009都表明映射键是无序的。因此,你不应该依赖订单在装货后到达那里 当然,在CPython的实现中有一个区别,在其他的实现中,它是从3.7开始的,而Python 3.6之前的dict是不排序的。PyYAML创建一个dict并按照从YAML文档中读取密钥的顺序填充它,因此3.6.5版本获得了密钥插入的顺序,而3.4.8则没有 如果您需要两个版本的行为相同,我建议您显式地对键进行排序:
for function in sort(conf['functions']):
如果您真的需要按照密钥在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)
这将获得Python2.7到3.7中的输出,就像在Python3.6.5中一样。在ruamel.yaml中,默认情况下执行yaml.load是安全的。您应该使用yaml.safe\u load,因为yaml.load是不必要的,而B被证明是不安全的。非常好的提示,谢谢!嗨,好吧,实际上是你描述的另一种方式。在3.6.5版本的Windows机器上,dict是无序的,而在3.4.8版本的Linux上,dict是无任何特定原因排序的。这就是为什么我想知道。我想要实现的是,函数下的标记的写入顺序应该保持不变。但是我现在解决了我的问题,添加了一个runorder,并将函数添加到一个字典中,使用runorder值作为键,这样就可以保持我想要的顺序。我认为排序与词汇排序之间存在一些混淆。您在3.6+中的排序是我在ruamel.orderedict文档中所称的插入排序,而不是排序排序。因此,放入dict中且未删除的第一个键是迭代时作为第一个键得到的,等等。如果YAML文件中的顺序是您想要的,那么ruamel.YAML将解决您的问题。有一个明确的键列表也可以。或者,制作一系列单键值项,例如通过转储显式OrderedICT来完成