代码之家  ›  专栏  ›  技术社区  ›  ragesz

python yaml转储特殊字符和多行

  •  1
  • ragesz  · 技术社区  · 6 年前

    我有一个 my_yaml.yml 包含以下内容的文件:

    my_yaml:
      person: >
        John|Doe|48,
        Jack|Black|39
      skills:
        - name: superhero
          abilities:
            - swim
            - run
      special_chars:
        - '! | " "'
        - '+ | " "'
        - '\ | " "'
        - 'Á | "A"'
        - 'É | "E"'
        - 'Å° | "U"'
        - 'Û | "U"'
    

    我想把它装进去然后倒进 my_yaml_new.yml 与原始输入文件完全相同的格式和字符的文件。我的代码是:

    import yaml
    my_yaml = yaml.load(open('my_yaml.yml', encoding='utf8'))  # without "utf8" encoding I get "'charmap' codec can't decode byte..." error
    

    我可以 dump 它进入控制台但是 1) 订单 abilities &安培; name 已更改:(

    yaml.dump(my_yaml, default_flow_style=False, allow_unicode=True)
    

    结果是:

    'my_yaml:\n  person: >\n    John|Doe|48, Jack|Black|39\n  skills:\n  - abilities:\n    - swim\n    - run\n    name: superhero\n  special_chars:\n  - \'! | " "\'\n  - + | " "\n  - \\ | " "\n  - Á | "A"\n  - É | "E"\n  - Ű | "U"\n  - Û | "U"\n'
    

    当我试图将其转储到一个文件中时:

    with open('my_yaml_new.yml', 'w') as outfile:
        yaml.dump(my_yaml, outfile, default_flow_style=False, allow_unicode=True)
    

    (二) 由于角色原因,我得到以下错误 Û 以下内容:

    unicodeencodeerror:'charmap'编解码器无法在中编码字符'\xdb' 位置0:字符映射到未定义

    如果我从输入中删除此行 我的“yaml.yml” 然后上面的文件转储成功,但是 3) 我的多行在 person 字符串进入一行:(

    my_yaml:
      person: >
        John|Doe|48, Jack|Black|39
      skills:
      - abilities:
        - swim
        - run
        name: superhero
      special_chars:
      - '! | " "'
      - + | " "
      - \ | " "
      - Á | "A"
      - É | "E"
      - Å° | "U"
    

    (四) 我的单引号(“)也从 special_chars 注意:(

    5) 还要注意的是 skills 没有缩进:.(

    我试过了 these 没有成功的解决方案。也没有 import ruamel.yaml as yaml 有帮助。


    更新

    好的,下面的大包装解决了问题 1) &安培; (四) ,我可以替换 > | 多行值,所以 3) 也解决了。也许 5) 不是一个大问题。但我仍然在和一些特殊的人物斗争,比如 _ Ǘ 所以我仍在寻找解决问题的方法 (二) ……

    from ruamel import yaml
    
        my_yaml = yaml.round_trip_load(open('dmy_yaml.yml', encoding='utf8'), preserve_quotes=True)
        with open('my_yaml_new.yml', 'w') as outfile:
            yaml.round_trip_dump(my_yaml, outfile, default_flow_style=False, allow_unicode=True)
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Anthon Rujikin    6 年前

    我不知道你为什么会遇到Unicode的问题。如果你有你的 my_yaml.yml 还有一个节目 try.py 以下内容:

    import sys
    import ruamel.yaml
    
    with open('my_yaml.yml') as fp:
        yaml_str = fp.read().replace(': >\n', ': |\n')
    
    yaml = ruamel.yaml.YAML()
    yaml.indent(mapping=2, sequence=4, offset=2)
    yaml.preserve_quotes = True
    data = yaml.load(yaml_str)
    new_file = 'my_yaml_new.yml'
    with open(new_file, 'w') as ofp:
        yaml.dump(data, ofp)
    

    然后产生:

    my_yaml:
      person: |
        John|Doe|48,
        Jack|Black|39
      skills:
        - name: superhero
          abilities:
            - swim
            - run
      special_chars:
        - '! | " "'
        - '+ | " "'
        - '\ | " "'
        - 'Á | "A"'
        - 'É | "E"'
        - 'Å° | "U"'
        - 'Û | "U"'
    

    在virtualenv中,对于ruamel.yaml为0.15.40的python2和python3。

    我用过:

    for n in 2 3 ; do  mktmpenv -p /opt/python/$n/bin/python -qq -i ruamel.yaml; python --version; python try.py; deactivate; done
    

    当然,这取决于(最新的)python 2和3的版本 /opt/python/2 响应 /opt/python/3 (它们在我的Linux开发系统上)。

    注意,Unicode没有显示任何问题, yaml.indent(mapping=2, sequence=4, offset=2) 保留源缩进,但您仍然需要将折叠的多行标量更改为文本样式(在读取到 yaml_str )因为ruamel.yaml不支持保存(主要是因为没有简单的方法以透明的方式指示原始折叠点)。