【问题标题】:Outputting YAML with Python: incorrect formatting without lists in input使用 Python 输出 YAML:输入中没有列表的格式不正确
【发布时间】:2019-06-29 22:37:56
【问题描述】:

我正在尝试从 Python 字典创建 YAML。到目前为止,我已经尝试过 PyYAML 和 ruamel.yaml 并且都具有相同的结果:如果输入字典不包含列表,则输出格式不正确。

这是脚本:

from ruamel import yaml
import sys

yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': ['photon torpedoes','phasers'], 'number': 1701}, sys.stdout)
print('\n')
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

这是输出:

armament: [photon torpedoes, phasers]
class: Galaxy
name: Enterprise
number: 1701

{class: Galaxy, name: Enterprise, number: 1701}

所需的输出是第二个 YAML 转储应该像第一个一样格式化。这是怎么回事?

【问题讨论】:

  • 你确定这是你脚本的输出吗? print('\n') 实际上会在 YAML 转储之间放置 两个 换行符。

标签: python yaml pyyaml ruamel.yaml


【解决方案1】:

您使用的是旧式 API,默认输出 任何叶子 流式节点。在您的情况下,列表/序列[photon torpedoes, phasers] 和您的秒转储(根级别 叶节点)。


假设您不仅想要解释为什么会发生这种情况,还想知道如何改变这种行为,使用新的 API,使用 ruamel.yaml.YAML 的实例,默认是让所有东西都流式,包括所有叶子节点:

from ruamel.yaml import YAML
import sys

yaml = YAML()

yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': ['photon torpedoes','phasers'], 'number': 1701}, sys.stdout)
print()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

给予:

name: Enterprise
class: Galaxy
armament:
- photon torpedoes
- phasers
number: 1701

name: Enterprise
class: Galaxy
number: 1701

仍然不是你想要的:-)

您现在有两种选择来获得您所指示的内容:第一个转储上的叶节点流样式和第二个转储上的叶节点块样式。

第一个是有一个实例 default_flow_style 集用于第一次转储和 第二次转储的“正常”:

from ruamel.yaml import YAML
import sys

yaml = YAML()

yaml.default_flow_style = None
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': ['photon torpedoes','phasers'], 'number': 1701}, sys.stdout)
print()
yaml = YAML()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

给出:

name: Enterprise
class: Galaxy
armament: [photon torpedoes, phasers]
number: 1701

name: Enterprise
class: Galaxy
number: 1701

第二个选项是在对象上显式设置流样式 你想作为序列输出。因此,您必须创建一个 ruamel.yaml.comments.CommentedSeq实例,正常使用 加载时保留流/块样式、cmets 等:

from ruamel.yaml import YAML, comments
import sys

yaml = YAML()

armaments = comments.CommentedSeq(['photon torpedoes','phasers'])
armaments.fa.set_flow_style()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'armament': armaments, 'number': 1701}, sys.stdout)
print()
yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701}, sys.stdout)

这也给出了:

name: Enterprise
class: Galaxy
armament: [photon torpedoes, phasers]
number: 1701

name: Enterprise
class: Galaxy
number: 1701

这第二个选项当然可以让你很好地控制(还有一个CommentedMap),因为你 可以在数据层次结构的所有级别上拥有这些对象,而不仅仅是在作为集合的叶子上。


请注意,从具有您想要的格式的 YAML 文件加载所需的输出时,您不必经历任何这些滑稽动作。在这种情况下,字典分别。类似列表的实例是使用正确的流/块样式创建的,因此当只是更改/添加值并转储时,输出不会意外更改。

【讨论】:

    【解决方案2】:

    这在documentation 中说明了如何进行一致的输出:

    yaml.dump({'name': 'Enterprise', 'class': 'Galaxy', 'number': 1701},
      sys.stdout,
      default_flow_style=False) # <- the important parameter
    
    class: Galaxy
    name: Enterprise
    number: 1701
    

    【讨论】:

      猜你喜欢
      • 2014-01-29
      • 1970-01-01
      • 2016-12-30
      • 2012-08-28
      • 1970-01-01
      • 2016-12-06
      • 2020-07-28
      • 2021-05-03
      相关资源
      最近更新 更多