我有一个 python 项目,我想在其中使用 YAML (pyYaml 3.11),特别是因为它“漂亮”并且用户可以在必要时轻松地在文本编辑器中进行编辑。不过,我的问题是,如果我将 YAML 引入 python 应用程序(因为我需要这样做)并编辑内容(因为我需要这样做),那么编写新文档通常不像我开始时那样漂亮。
pyyaml 文档非常糟糕——甚至没有记录转储函数的参数。我找到了 http://dpinte.wordpress.com/2008/10/31/pyaml-dump-option/ .但是,我仍然缺少我需要的信息。 (我开始查看源代码,但它似乎不是最吸引人的。如果我在这里没有得到解决方案,那是我唯一的办法。)
我从一个看起来像这样的文档开始:
- color green : inputs : - port thing : widget-hint : filename widget-help : Select a filename - port target_path : widget-hint : path value : 'thing' outputs: - port value: widget-hint : string text : | I'm lost and I'm found and I'm hungry like the wolf.
加载到 python (yaml.safe_load(s)) 后,我尝试了几种将其转储出来的方法:
>>> print yaml.dump( d3, default_flow_style=False, default_style='' ) - color green: inputs: - port thing: widget-help: Select a filename widget-hint: filename - port target_path: value: thing widget-hint: path outputs: - port value: widget-hint: string text: 'I''m lost and I''m found and I''m hungry like the wolf. '
>>> print yaml.dump( d3, default_flow_style=False, default_style='|' ) - "color green": "inputs": - "port thing": "widget-help": |- Select a filename "widget-hint": |- filename - "port target_path": "value": |- thing "widget-hint": |- path "outputs": - "port value": "widget-hint": |- string "text": | I'm lost and I'm found and I'm hungry like the wolf.
理想情况下,我希望“短字符串”不使用引号,就像在第一个结果中那样。但我希望将多行字符串写成 block ,就像第二个结果一样。我想从根本上说,我正在尝试尽量减少文件中不必要引号的激增,我认为这会使在文本编辑器中编辑变得更加烦人。
有没有人有这方面的经验?
最佳答案
如果你可以使用 ruamel.yaml(免责声明:我是这个增强版 PyYAML 的作者)你可以
往返原始格式(YAML 文档存储在文件 org.yaml
中):
import sys
import ruamel.yaml
from pathlib import Path
file_org = Path('org.yaml')
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
data = yaml.load(file_org)
yaml.dump(data, sys.stdout)
给出:
- color green:
inputs:
- port thing:
widget-hint: filename
widget-help: Select a filename
- port target_path:
widget-hint: path
value: 'thing'
outputs:
- port value:
widget-hint: string
text: |
I'm lost and I'm found
and I'm hungry like the wolf.
您输入的缩进/格式不一致,尽管在 ruamel.yaml 中有更多控制 输出比在 PyYAML 中的输出,你无法得到准确的原始数据:
- 您有时 (
color green :
) 在值指示符 (:
) 之前有一个空格,有时您 不要(输出:
)。除了对根级别 key 的特殊控制外,ruamel.yaml 始终将 值指示符直接与键相邻。 - 您的根级序列缩进两列, block 序列指示符 (
-
) 的偏移量为零 (这是默认的 ruamel.yaml 使用)。其他缩进五,三个偏移。 ruamel.yaml 不能单独/不一致地格式化序列,我建议使用默认值,因为你的根 集合是一个序列。 - 您的映射有时会缩进三列(key
color green
的值)有时 两个(例如键port target_path
的值)。同样,ruamel.yaml 无法单独/不一致地格式化这些内容 - 如果你
不要将 block 缩进指示符附加到
|
指示符(例如使用|4
)。所以这 额外的缩进将丢失
如您所见,设置 yaml.preserv_quotes
会保留 'thing'
周围多余的引号
不是你想要的,它没有在这个例子的其余部分设置。
以下“规范化”了所有三个示例:
import sys
import ruamel.yaml
from pathlib import Path
LT = ruamel.yaml.scalarstring.LiteralScalarString
file_org = Path('org.yaml')
file_plain = Path('plain.yaml')
file_block = Path('block.yaml')
def normalise(d):
if isinstance(d, dict):
for k, v in d.items():
d[k] = normalise(v)
return d
if isinstance(d, list):
for idx, elem in enumerate(d):
d[idx] = normalise(elem)
return d
if not isinstance(d, str):
return d
if '\n' in d:
if isinstance(d, LT):
return d # already a block style literal scalar
return LT(d)
return str(d)
yaml = ruamel.yaml.YAML()
for fn in [file_org, file_plain, file_block]:
data = normalise(yaml.load(file_org))
yaml.dump(data, fn)
assert file_org.read_bytes() == file_plain.read_bytes()
assert file_org.read_bytes() == file_block.read_bytes()
print(file_block.read_text())
给出:
- color green:
inputs:
- port thing:
widget-hint: filename
widget-help: Select a filename
- port target_path:
widget-hint: path
value: thing
outputs:
- port value:
widget-hint: string
text: |
I'm lost and I'm found
and I'm hungry like the wolf.
因此,正如您所指出的,如果标量有换行符,您将获得 block 样式文字标量,并且 如果是标量,则没有 block 样式 和 没有引号 它没有换行符。
关于python - pyyaml 的漂亮输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24418449/