我如何控制 PyYAML 用于我的数据的标量形式?

新手上路,请多包涵

我有一个具有短字符串属性和长多行字符串属性的对象。我想将短字符串写为 YAML 引用标量,将多行字符串写为文字标量:

 my_obj.short = "Hello"
my_obj.long = "Line1\nLine2\nLine3"

我希望 YAML 看起来像这样:

 short: "Hello"
long: |
  Line1
  Line2
  Line3

我如何指示 PyYAML 执行此操作?如果我调用 yaml.dump(my_obj) ,它会产生类似字典的输出:

 {long: 'line1

    line2

    line3

    ', short: Hello}

(不知道为什么 long 是那样的双倍行距……)

我可以指示 PyYAML 如何处理我的属性吗?我想同时影响顺序和样式。

原文由 Ned Batchelder 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 973
2 个回答

基于 Python 中任何支持将长字符串转储为块文字或折叠块的 yaml 库?

 import yaml
from collections import OrderedDict

class quoted(str):
    pass

def quoted_presenter(dumper, data):
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
yaml.add_representer(quoted, quoted_presenter)

class literal(str):
    pass

def literal_presenter(dumper, data):
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
yaml.add_representer(literal, literal_presenter)

def ordered_dict_presenter(dumper, data):
    return dumper.represent_dict(data.items())
yaml.add_representer(OrderedDict, ordered_dict_presenter)

d = OrderedDict(short=quoted("Hello"), long=literal("Line1\nLine2\nLine3\n"))

print(yaml.dump(d))

输出

short: "Hello"
long: |
  Line1
  Line2
  Line3

原文由 jfs 发布,翻译遵循 CC BY-SA 3.0 许可协议

爱上 @lbt 的方法,我得到了这段代码:

 import yaml

def str_presenter(dumper, data):
  if len(data.splitlines()) > 1:  # check for multiline string
    return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
  return dumper.represent_scalar('tag:yaml.org,2002:str', data)

yaml.add_representer(str, str_presenter)

# to use with safe_dump:
yaml.representer.SafeRepresenter.add_representer(str, str_presenter)

它使每个多行字符串成为块文字。

我试图避免猴子修补部分。完全归功于@lbt 和@JFSebastian。

原文由 xenosoz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题