【问题标题】:Python YAML dump special character and multiple linesPython YAML 转储特殊字符和多行
【发布时间】:2018-11-28 05:21:04
【问题描述】:

我有一个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) abilitiesname 的顺序已更改 :(

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)

2)由于字符Û,我收到以下错误:

UnicodeEncodeError: 'charmap' 编解码器无法对字符 '\xdb' 进行编码 位置 0:字符映射到未定义

如果我从输入 my_yaml.yml 文件中删除这一行,那么上面的转储是成功的,但是 3) 我在person 字符串中的多行变成了一行:(

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

4) 而且我的单引号 (') 从 special_chars 中消失了 :(

5)还要注意skills的元素没有缩进:(

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


更新

好的,下面这个很棒的包解决了1)4)的问题,我可以将>替换为|多行值,所以 3) 也解决了。也许 5) 不是一个大问题。但是我仍然在处理ÛǗ 等特殊字符,所以我仍在寻找解决问题的方法2)...

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)

【问题讨论】:

    标签: python yaml pyyaml ruamel.yaml


    【解决方案1】:

    我不确定您为什么会遇到 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"'
    

    在具有 ruamel.yaml 0.15.40 的 Python2 和 Python3 的 virtualenv 中。

    我用过:

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

    这当然依赖于安装在/opt/python/2 下的 Python 2 和 3 的(最新)版本。 /opt/python/3(它们在我的 Linux 开发系统上)。

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

    【讨论】:

    • 谢谢,这个解决方案完美!我不知道为什么,但是当我读取文件时,我总是必须强制使用encoding='utf-8,让它成为pandas.read_csv() 或简单的with open()。 (sys.getdefaultencoding() 返回 utf-8...)
    • 这可能与您的 Python 的编译方式有关,但我不确定。
    猜你喜欢
    • 2020-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 2016-08-29
    • 1970-01-01
    • 2015-02-20
    相关资源
    最近更新 更多