Python 3.x 使用Python更改YAML中的特定变量

Python 3.x 使用Python更改YAML中的特定变量,python-3.x,ansible,yaml,pyyaml,ruamel.yaml,Python 3.x,Ansible,Yaml,Pyyaml,Ruamel.yaml,我有一个YAML变量文件用于Ansible。 我正在尝试构建一个python脚本来更改YAML文件中的特定变量 YAML文件accsw01.yml如下所示: interface_vars: - {interface: Ethernet1/1, description: Test_interface_1, access_vlan: 10} - {interface: Ethernet1/2, description: Test_interface_2, access_vlan: 20} 我使用w

我有一个YAML变量文件用于Ansible。 我正在尝试构建一个python脚本来更改YAML文件中的特定变量

YAML文件accsw01.yml如下所示:

interface_vars:
- {interface: Ethernet1/1, description: Test_interface_1, access_vlan: 10}
- {interface: Ethernet1/2, description: Test_interface_2, access_vlan: 20}
我使用while循环在YAML文件中找到正确的接口变量:

interface = input("Enter interface: ")
yaml_file_printout = pprint.PrettyPrinter(indent=2)
with open("/ansible/inventories/test/host_vars/accsw01.yml", "r") as yaml_file:
    yaml_read = yaml.load(yaml_file, Loader=yaml.FullLoader)
    interface_count = 0
    while True:
        output_interface = yaml_read["interface_vars"][interface_count]["interface"]
        if interface != output_interface:
            interface_count += 1
        elif interface == output_interface:
            yaml_file_printout.pprint(yaml_read["interface_vars"][interface_count])
            break
我怎样才能让python改变接口Ethernet1/2上的访问vlan,同时保持文件的其余部分不变

我试过:

用PyYAML追加文件,但这只是将新变量块粘贴在YAML文件的顶部


使用ruamel.yaml更改变量,但尽管它更改了变量,但它会从yaml文件中删除所有格式,并且不会将变量显示为dict

首先,您通常无法附加到yaml文件,您必须将文件读入数据结构,更改(附加,删除)数据结构,然后把它倒回去

第二,你不应该在去做的时候不必要地打开一个文件 其他事情。执行
yaml.load()
后(无论是在ruamel.yaml中还是在 PyYAML)数据被读取,因此您应该通过对代码进行dedent来退出with语句

您的程序不会将读取的数据更改为
yaml\u read
,因此我尝试了一些明确的更改:

import sys
import pprint
import ruamel.yaml

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
yaml.default_flow_style=None

interface = 'Ethernet1/1'
yaml_file_printout = pprint.PrettyPrinter(indent=2)
with open("interface.yaml", "r") as yaml_file:
    data = yaml.load(yaml_file)  
interface_count = 0
while True:
    output_interface = data["interface_vars"][interface_count]["interface"]
    if interface != output_interface:
        interface_count += 1
    elif interface == output_interface:
        yaml_file_printout.pprint(data["interface_vars"][interface_count])
        break

print('------')
yaml.dump(data, sys.stdout)
print('------')
data['interface_vars'][1]['access_vlan'] = 30
data['interface_vars'].append(dict(interface='Ethernet1/3', description='Test_interface_3', access_vlan='5'))
yaml.dump(data, sys.stdout)
其中:

{ 'access_vlan': 10,
  'description': 'Test_interface_1',
  'interface': 'Ethernet1/1'}
------
interface_vars:
- {interface: Ethernet1/1, description: Test_interface_1, access_vlan: 10}
- {interface: Ethernet1/2, description: Test_interface_2, access_vlan: 20}
------
interface_vars:
- {interface: Ethernet1/1, description: Test_interface_1, access_vlan: 10}
- {interface: Ethernet1/2, description: Test_interface_2, access_vlan: 30}
- {interface: Ethernet1/3, description: Test_interface_3, access_vlan: '5'}
而不是全局生成叶节点流样式(使用
yaml.default\u flow\u style=None
)您还可以包装 附加在
ruamel.yaml.comments.CommentedMap()中,键入更精细的
控制如何转储数据(有一些关于如何转储数据的详细信息
这样做)

还请注意
对于YAML文件,
。YAML
已经有超过13年的历史了。

太棒了,谢谢!我在其他帖子上看到了你的一些回复,他们一直在帮助我。如果你有更多的问题,你知道去哪里。但请尽量在你的问题中包含完整的、最少的、有效的程序,这样你就更容易发现哪里出了问题、假设不正确等等。