读取和更改.yaml文件中的对象(使用PyYAML)

时间:2018-12-21 18:55:21

标签: python yaml pyyaml

我环顾了几个小时,无所不包。这意味着我比我了解得多。

main:
    user-settings:
        accountID: 666
        timestamp: 00:00
    client settings:
        nickname: "mainPC"
        region: "OK"

例如,如何打印“帐户ID”和“区域”?

如果我想将accountID从666更改为102,该怎么办?

1 个答案:

答案 0 :(得分:0)

您无法真正做到您在PyYAML中所要求的,甚至对于小型企业也是如此 你的例子。打印请求的值有效,但是当您更新时 您的YAML,您会看到它更改了 除了accountID的值。假设您的YAML文件是 test.yaml

from pathlib import Path
import yaml

yaml_file = Path('test.yaml')

with yaml_file.open() as fp:
    data = yaml.safe_load(fp)
user_settings = data['main']['user-settings']
print('acount id:', user_settings['accountID'])
user_settings['accountID'] = 102
print('region:   ', data['main']['client settings']['region'])

with yaml_file.open('w') as fp:
    yaml.safe_dump(data, fp, indent=4, default_flow_style=False)

此输出:

acount id: 666
region:    OK

test.yaml的内容将是:

main:
    client settings:
        nickname: mainPC
        region: OK
    user-settings:
        accountID: 102
        timestamp: 00:00

对于YAML文件中的任何映射,您都会得到一个Python dict,并且 如果您的YAML中有序列,则使用Python list。打印 所需的值,您只需遍历嵌套的dict

如您所见,您松开了OKmainPC周围的引号,您 在00:00附近吸引他们。后者是因为PyYAML尚未 更新以处理回传的最新YAML 1.2标准 2009。在YAML 1.1中,形式为XX:YY的标量被假定为 sexagesimals和 转换(并转储)为整数(如果有 小数点)。您的00:00作为字符串加载是因为 前导零。如果它是12:00,那么您的输出文件将 是timestamp: 720

映射中键的顺序也不是 保留。语义上这没有什么区别,但是如果此文件是 在版本控制下,这些更改很快就会变得令人困惑。

您应使用safe_load(),因为“标准” load()可能不安全 不受控制的YAML输入,尽管有文件记录,但大多数人没有 意识到这一点,也基本上没有必要。 (不安全为 或什至更糟。)


如果要更新YAML文件,建议使用 ruamel.yaml(免责声明:我 是该软件包的作者。

from pathlib import Path
import ruamel.yaml

yaml_file = Path('test.yaml')

yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4)
yaml.preserve_quotes = True
data = yaml.load(yaml_file)

user_settings = data['main']['user-settings']
print('acount id:', user_settings['accountID'])
user_settings['accountID'] = 102
print('region:   ', data['main']['client settings']['region'])

yaml.dump(data, yaml_file)

它还会输出:

acount id: 666
region:    OK

test.yaml的内容将是:

main:
    user-settings:
        accountID: 102
        timestamp: 00:00
    client settings:
        nickname: "mainPC"
        region: "OK"

不仅正确地保留了引号,而且不必 引用00:00,因为ruamel.yaml处理YAML 1.2,其中 六性动物完全掉下¹。映射中键的顺序 被保留。

如果在test.yaml中有注释,那么PyYAML将丢弃这些注释, 而ruamel.yaml也保留这些内容。

ruamel.yaml中,默认的YAML()使用安全的加载程序。


¹如果创建Sexagesimal,您仍然可以使用六进制 分类并适当标记它们。在这种情况下,您也可以决定 具有前导零(!sexagesimal 00:00),并正确转储这些值 返回为带标签的,未引用的标量。