在 python 中将字典写入 YAML 文件时出现问题

Issue in writing the dictionary into YAML file in python

我想将字典写入 YAML 文件,这是我目前正在做的事情

from ruamel.yaml import YAML

Flavor_Details = {'Flavor_Details':{
                  'type': 'OS::Nova::Flavor', 
                  'properties': {
                                 'name': 'test-flavor', 
                                 'extra_specs': {"hw:cpu_policy": 'shared'}, 
                                 'ram': 4096, 
                                 'vcpus': 4, 
                                 'disk': 8
                                }
                 }}

output_section = {
                    'server_public_ip':{
                        'description': 'Floating IP address of server',
                        'value': { 'get_attr': [ 'server_floating_ip', 'ip' ] }
                    }
                }

resources_dict = {}
resources_dict.update(Flavor_Details)
resources_dict.update(output_section)

yaml = YAML(typ= 'safe')

with open('test.yaml', 'w') as outfile:
     yaml.dump(resources_dict,outfile)

这是 YAML 文件中的结果

Flavor_Details:
    properties:
      disk: 8
      extra_specs: {hw:cpu_policy: shared}
      name: test-flavor
      ram: 4096
      vcpus: 4
    type: OS::Nova::Flavor
server_public_ip:
    description: Floating IP address of server
    value:
      get_attr: [server__floating_ip, ip]

但我想要这样的结果:

Flavor_Details:
    properties:
      disk: 8
      extra_specs: {"hw:cpu_policy": shared}
      name: test-flavor
      ram: 4096
      vcpus: 4
    type: OS::Nova::Flavor
server_public_ip:
    description: Floating IP address of server
    value: {get_attr: [server__floating_ip, ip]}

我想要 "hw:cpu_policy" 作为字符串,因为 hwcpu_policy 之间的 :value 我想成为喜欢{get_attr: [server__floating_ip, ip]}这个。

有没有办法得到这样的东西?

你可以得到你想要的东西,但不是使用安全翻车机。基于 C 的底层代码不允许 以获得您想要的细粒度控制。

您需要使用默认的(往返)转储程序,它允许这种 详细的控制,因为它需要它来尝试并保留往返的布局。

我希望你意识到 YAML 文件中 hw:cpu_policy 周围的引号是 根据 YAML 规范不需要,但有一些不正确的 YAML 解析器的实现有问题。

import sys
import ruamel.yaml

def Q(s):
    return ruamel.yaml.scalarstring.DoubleQuotedScalarString(s)

def F(*args, **kw):
    x = ruamel.yaml.comments.CommentedMap()
    x.fa.set_flow_style()
    for a in args:
        x.update(a)
    x.update(kw)
    return x


Flavor_Details = {'Flavor_Details':{
                  'type': 'OS::Nova::Flavor', 
                  'properties': {
                                 'name': 'test-flavor', 
                                 'extra_specs': F({Q("hw:cpu_policy"): 'shared'}), 
                                 'ram': 4096, 
                                 'vcpus': 4, 
                                 'disk': 8
                                }
                 }}

output_section = {
                    'server_public_ip':{
                        'description': 'Floating IP address of server',
                        'value': F(get_attr=['server_floating_ip', 'ip'])
                    }
                }

resources_dict = {}
resources_dict.update(Flavor_Details)
resources_dict.update(output_section)

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.dump(resources_dict, sys.stdout)

给出:

Flavor_Details:
  type: OS::Nova::Flavor
  properties:
    name: test-flavor
    extra_specs: {"hw:cpu_policy": shared}
    ram: 4096
    vcpus: 4
    disk: 8
server_public_ip:
  description: Floating IP address of server
  value: {get_attr: [server_floating_ip, ip]}

另一种方法是返回 PyYAML 并对输出字符串使用简单的替换规则。还要注意 requoted 条目 extra_specsvalue.

import yaml as yl

Flavor_Details = {'Flavor_Details': {
                  'type': 'OS::Nova::Flavor',
                  'properties': {
                      'name': 'cloudpeak-test-flavor',
                      'extra_specs': "{'hw:cpu_policy': shared}",
                      'ram': 4096,
                      'vcpus': 4,
                      'disk': 8
                  }
                  }}

output_section = {
    'server_public_ip': {
        'description': 'Floating IP address of server',
        'value': '{get_attr: [server_floating_ip, ip]}'
    }
}

resources_dict = {}
resources_dict.update(Flavor_Details)
resources_dict.update(output_section)

out_str = yl.safe_dump(resources_dict)
out_str = out_str.replace("''", '"')
out_str = out_str.replace("'", '')

print(out_str)

with open('test-yl.yaml', 'w') as outfile:
    outfile.write(out_str)

给出:

Flavor_Details:
  properties:
    disk: 8
    extra_specs: {"hw:cpu_policy": shared}
    name: cloudpeak-test-flavor
    ram: 4096
    vcpus: 4
  type: OS::Nova::Flavor
server_public_ip:
  description: Floating IP address of server
  value: {get_attr: [server_floating_ip, ip]}