Python YAML 转储特殊字符和多行



我有一个包含以下内容的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|39n  skills:n  - abilities:n    - swimn    - runn    name: superheron  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的元素没有缩进:(

我已经尝试了这些解决方案,但没有成功。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)

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

在 Python2 和 Python3 的虚拟环境中,ruamel.yaml 0.15.40。

我使用过:

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/2resp 下安装。/opt/python/3(它们在我的 Linux 开发系统上(。

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

最新更新