如何保持锚点和别名不变?

问题描述 投票:0回答:2

例如输入文件

username: &username john
password: &password  xyz
server: &servername 192.168.0.1
host:
 server: *servername
 username: *username
 password: *password

输出文件显示

null
而不是
*servername
*username
*password
,如果 O 执行
yaml.dump

username: &username john
password: &password  xyz
server: &servername 192.168.0.1
host:
 server: null
 username: null
 password: null

这样读

with open(file_name, 'r') as file: 
    loaded_data = yaml.safe_load(file) 

写作

with open('filename.yaml', 'w') as f: 
    data = yaml.dump(loaded_data, f, sort_keys=False,default_flow_style=False,allow_unicode = True, indent=2)
python yaml pyyaml
2个回答
2
投票

对于 Python 中 YAML 的往返(加载、更改、转储),我建议使用

ruamel.yaml
(免责声明:我是该包的作者)。它支持 YAML 1.2,保留注释和标签(甚至 当标记简单标量时(如您的情况),PyYAML 都无法做到:

import sys
from pathlib import Path
import ruamel.yaml

in_file = Path('input.yaml')
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=1)       # to match your input, default is 2
data = yaml.load(in_file)
yaml.dump(data, sys.stdout)  # replace sys.stdout with in_file to overwrite the input

给出:

username: &username john
password: &password xyz
server: &servername 192.168.0.1
host:
 server: *servername
 username: *username
 password: *password

0
投票

@anthon,上面对我有用,但是当我操作 YAML 文件对象时,它会用锚点替换别名。看看这个:

使用上述代码加载 YAML 后,当我将其发送到 stdout 时,我的 YAML 的一部分看起来像这样:

channels:
  topic:
    bindings:
      kafka:
        topic: *tpn
        partitions: *prt
        topicConfiguration:
          cleanup.policy: [*clp]

然后我从文档顶部的另一个对象中删除环境。每个环境都包含通过别名解析的主题的锚点,我想删除除指定为函数输入的环境之外的所有环境,以便在处理 YAML 文件/asyncapi 规范时解析正确的锚点。

完成操作后,带有别名的通道如下所示:

channels:
  topic:
    bindings:
      kafka:
        topic: &tpn mytopic
        partitions: &prt 12
        topicConfiguration:
          cleanup.policy: [&clp delete]

如您所见,它正在解析定义的锚点的别名,更奇怪的是它还将锚点本身添加到解析值中。

你知道如何解决这个问题吗?我当前的代码是这样的:

import sys
from pathlib import Path
import ruamel.yaml
import warnings
from ruamel.yaml.error import ReusedAnchorWarning

warnings.simplefilter("ignore", ReusedAnchorWarning)

def remove_unused_envs(yaml_file, target_env):
    yaml = ruamel.yaml.YAML()

    in_file = Path(yaml_file)
    data = yaml.load(in_file)
    yaml.dump(data, sys.stdout)

    # Navigate to the 'envs' section
    envs = data['x-es']['vendor']['envs']

    # Iterate through each environment and delete the ones not matching target_env
    for env_name in list(envs):
        if env_name != target_env:
            del envs[env_name]

    yaml.dump(data, sys.stdout)

# Example usage:
remove_unused_envs('C://temp//asyncapi-spec.yaml', 'test')
© www.soinside.com 2019 - 2024. All rights reserved.