【问题标题】:Yaml dump python dictionary as mapping without single quotesYaml 将 python 字典转储为不带单引号的映射
【发布时间】:2020-11-16 13:25:55
【问题描述】:

我想将 dict 转储到没有引号的 yaml 文件中。基本上就像一个映射

import yaml

windows_list = []
server_list = ['abc-def-01', 'pqr-str-02']
site_list = ['dev', 'prod']

server_dict = dict(zip(server_list, site_list))

for k,v in server_dict.items():
    a = '{ SERVER: '+k+', SITE: '+v+' }'
    windows_list.append(a)

final_dict = {'service':'something','servers': windows_list}

with open('config.yml', 'w') as yaml_file:
    yaml.dump(final_dict, yaml_file, default_flow_style=False)

config.yml 的输出如下:

service: some name
servers:
- '{ SERVER: abc-def-01, SITE: dev }'
- '{ SERVER: pqr-str-02, SITE: prod }'

我不想要它周围的引号。我希望它是一个没有引号的映射

期望的输出

service: some name
servers:
- { SERVER: abc-def-01, SITE: dev }
- { SERVER: pqr-str-02, SITE: prod }

我阅读了this post,它说如果您有特殊字符,则无法删除引号,但我想知道是否有某种解决方法来实现我想要的。

【问题讨论】:

    标签: python yaml pyyaml ruamel.yaml


    【解决方案1】:

    需要引号是因为您创建和转储的字符串看起来像流式 映射。换句话说,当您加载您想要的内容时,您会得到不同的 数据结构比您“手动”创建的(或从您获得的输出中加载)。

    如果您遇到这种情况,最好的办法是加载您想要获取的内容,然后 转储 Python 数据结构,以便您知道需要创建什么。这也验证了你想要的是否真的是 YAML:

    import sys
    import ruamel.yaml
    
    yaml_str = """\
    service: some name
    servers:
    - { SERVER: abc-def-01, SITE: dev }
    - { SERVER: pqr-str-02, SITE: prod }
    """
    
    yaml = ruamel.yaml.YAML(typ='safe')
    data = yaml.load(yaml_str)
    print(data)
    

    给出:

    {'service': 'some name', 'servers': [{'SERVER': 'abc-def-01', 'SITE': 'dev'}, {'SERVER': 'pqr-str-02', 'SITE': 'prod'}]}
    

    如您所见,该序列由字典组成,因此您需要追加:

    import sys
    import ruamel.yaml
    
    
    windows_list = []
    server_list = ['abc-def-01', 'pqr-str-02']
    site_list = ['dev', 'prod']
    
    server_dict = dict(zip(server_list, site_list))
    
    for k,v in server_dict.items():
        a = { 'SERVER': k, 'SITE': v }
        windows_list.append(a)
    
    final_dict = {'service':'something', 'servers': windows_list}
    
    yaml = ruamel.yaml.YAML()
    yaml.default_flow_style = None
    yaml.dump(final_dict, sys.stdout)
    

    结果:

    service: something
    servers:
    - {SERVER: abc-def-01, SITE: dev}
    - {SERVER: pqr-str-02, SITE: prod}
    

    顺便说一句。自 2006 年 9 月起,YAML 文件的推荐扩展名为 .yaml

    【讨论】:

    • 谢谢@Anthon。工作,正是我想要的。我接受了你的回答。
    【解决方案2】:

    如果要输出字典,不要构造字符串。改为构造一个字典:

    import yaml
    
    windows_list = []
    server_list = ['abc-def-01', 'pqr-str-02']
    site_list = ['dev', 'prod']
    
    server_dict = dict(zip(server_list, site_list))
    
    for k,v in server_dict.items():
        windows_list.append({'SERVER': k, 'SITE': v})
    
    final_dict = {'service':'something','servers': windows_list}
    
    with open('config.yml', 'w') as yaml_file:
        yaml.dump(final_dict, yaml_file, default_flow_style=False)
    

    这将输出

    servers:
    - SERVER: abc-def-01
      SITE: dev
    - SERVER: pqr-str-02
      SITE: prod
    service: something
    

    如果您希望项目以流样式表示,您可以使用自定义表示器:

    import yaml
    
    windows_list = []
    server_list = ['abc-def-01', 'pqr-str-02']
    site_list = ['dev', 'prod']
    
    class ServerMap:
        def __init__(self, server, site):
            self.server = server
            self.site = site
    
    def servermap_representer(dumper, data):
        return dumper.represent_mapping('tag:yaml.org,2002:map',
                {'SERVER': data.server, 'SITE': data.site}, [True, True])
    
    yaml.add_representer(ServerMap, servermap_representer)
    
    server_dict = dict(zip(server_list, site_list))
    
    for k,v in server_dict.items():
        windows_list.append(ServerMap(k, v))
    
    final_dict = {'service':'something','servers': windows_list}
    
    with open('config.yml', 'w') as yaml_file:
        yaml.dump(final_dict, yaml_file, default_flow_style=False)
    

    输出:

    servers:
    - {SERVER: abc-def-01, SITE: dev}
    - {SERVER: pqr-str-02, SITE: prod}
    service: something
    

    【讨论】:

    • 谢谢@flyx。尝试过并且有效,但我接受了 Anthon 的回答,因为它不会改变值的顺序。
    【解决方案3】:

    试试这个:

    for k,v in server_dict.items():
        a = { 'SERVER': f'{k}', 'SITE': f'{v}' }
        windows_list.append(a)
    
    final_dict = {'service':'something','servers': windows_list}
    
    with open('config.yml', 'w') as yaml_file:
        yaml.dump(final_dict, yaml_file, default_flow_style=False)
    

    它将以 yaml 格式/结构准确生成您需要的内容:

    servers:
    - SERVER: abc-def-01
      SITE: dev
    - SERVER: pqr-str-02
      SITE: prod
    service: something
    

    HTH

    【讨论】:

    • 感谢您的回答!我需要 YAML 与所需输出中的完全一样。 Anthon 的回答更适合我的情况。
    猜你喜欢
    • 2021-05-13
    • 2019-01-16
    • 2022-07-20
    • 2021-06-26
    • 1970-01-01
    • 2019-03-16
    • 2018-11-04
    • 1970-01-01
    • 2017-11-27
    相关资源
    最近更新 更多