【问题标题】:Strings containing " - " always break onto newline with ruamel.yaml包含“ - ”的字符串总是用 ruamel.yaml 换行
【发布时间】:2019-01-03 17:18:00
【问题描述】:

我是一个 Python 3.7 项目中的 YAML 新手,我决定使用 ruamel.yaml 来帮助我入门。我打算用它来存储与一些视频文件相关的元数据。

我正在使用以下代码创建 YAML 文件:

data[filename] = [{'video': video_path},
                  {'key_frame': frame_path},
                  {'processed': get_timestamp()}]
yaml.dump(data, file_handle)

创建的 YAML 文件如下所示:

video.mp4:
- video: /Users/xyz/video.mp4
- key_frame: /Users/xyz/imgOutput/frame
    - Trigger.jpg
- processed: '2018-07-26 17:09:06'

问题在于 key_frame 是一个名为“frame - Trigger.jpg”的文件。但是,该行总是在文件名中的“ - ”(即空格-破折号-空格)处中断。结果是,作为一个人类可读的文件,它看起来非常错误。事实上,当它被读回(使用 yaml.open)时,它被正确处理,并被视为应有的单个字符串文件名。只是 YAML 文件中的格式有问题。

对原因有什么想法吗?这是预期的行为吗?我已经尝试了许多不同的方式来引用字符串以防万一(这没有什么区别 - 甚至引用它会分开行),但从代码意义上讲,它从根本上是有效的 - 但作为 YAML 的大卖重点是人类可读的文件,最好了解导致它的原因以及如何修复它。

【问题讨论】:

  • 做更多的实验: - 如果字符串是frame - trigger.jpg,它会像上面一样中断(在新行上破折号)。 - 如果字符串是frame- trigger.jpg,它会中断(但在第一行保留破折号)。 - 如果字符串是frame -trigger.jpg,它会中断(并且破折号在新行上)。 - 如果字符串是frame-trigger.jpg,它不会换行。所以本质上,一个或两边有空格的破折号会导致一个换行符被添加到格式中,但是当 ruamel.yaml 读回它时,这个换行符会被忽略。
  • 如果您的问题不完整,请不要添加评论,使用附加信息更新问题。不要不要在新文本之后使用Edit::始终确保文本是一个连贯的整体。正如我的回答中所指出的,总是提供了一个最小但完整的工作程序来产生输出(或错误)。如果您不这样做,您可能会关闭您的帖子;更容易发现哪里出错了;您可能会在最小化程序以重现不需要的行为的过程中找到解决方案。

标签: python-3.x yaml ruamel.yaml


【解决方案1】:

在 YAML 中,纯标量(即没有单引号或双引号的标量)可以包装到空白处的缩进换行符。这就是正在发生的事情。

重现这一点很困难,因为您的问题很不完整,但从输出中可以很容易地看到一些东西:

  • datadict
  • filenamevideo_pathframe_path 被定义为字符串。
  • file_handle 可能是为写入而打开的某个文件流。

其他的不太容易推断:

  • get_timestamp() 不会返回 datetime.datetime() 实例,正如人们对它的名称所期望的那样,而是它的字符串表示形式。为防止此字符串被解释为时间戳,必须将其引用。
  • 您正在使用默认的YAML() 实例(等于typ='rt'),因为非默认实例会以流样式(- {video: /Users/xyz/video.mp4} 等)编写叶映射

有了这个和适当的imports,你可以制作一个正常运行的程序:

import datetime
import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML(typ='rt')

def get_timestamp():
    return datetime.datetime(2018, 7, 26, 17, 9, 6).isoformat(sep=' ', timespec='seconds')

data = {}
filename = 'video.mp4'
video_path = '/Users/xyz/video.mp4'
frame_path = '/Users/xyz/imgOutput/frame - Trigger.jpg'
file_handle = sys.stdout

data[filename] = [{'video': video_path},
                  {'key_frame': frame_path},
                  {'processed': get_timestamp()}]
yaml.dump(data, file_handle)

这个输出:

video.mp4:
- video: /Users/xyz/video.mp4
- key_frame: /Users/xyz/imgOutput/frame - Trigger.jpg
- processed: '2018-07-26 17:09:06'

所以我们忘记了一些事情,那就是:

yaml.width = 24  # range from 24-38 inclusive

你得到你的输出:

video.mp4:
- video: /Users/xyz/video.mp4
- key_frame: /Users/xyz/imgOutput/frame
    - Trigger.jpg
- processed: '2018-07-26 17:09:06'

所以只需删除 yaml.width = 行,你就应该准备好了。


下次请提供一个实际产生输出的最小但完整的功能程序。

我的猜测是您的 frame_path 比您在此处显示的要长得多,并且您没有用户 xyz。这会导致您超过默认宽度(在发射器中定义为 80)和要换行的普通标量。只需设置yaml.width = 4096 或您的标量长度和嵌套深度所需的任何值。

如果怀疑 YAML 输出是否正确,请将其读回(使用 YAML(typ='safe').load(input_stream),它应该会生成原始数据。

【讨论】:

  • 感谢您提供如此全面的答案。抱歉错过了问题中的一些细节,我试图专注于我认为最相关的部分。但绝对同意一些最小的功能代码会更有帮助。
【解决方案2】:

破折号没有什么特别之处。如果字符串长于某个阈值,它将在之后的第一个 空格 处中断。您提供的示例不会为我重现此行为,但较长的字符串会。

生成的 YAML 有效。任何字符串,无论是否被引用,都可以分成几行。

也许您可以调整 ruamel 中的阈值。不过,我在文档中找不到任何内容。

(另见我的文章Strings in YAML

【讨论】:

  • 啊,就是这样——事实上它是长字符串中的第一个空格,而 ruamel 将字符串中断的时间超过了某个点。谢谢! :O)
  • 只是为了确认您可以通过设置yaml.width = 240 来调整行长/换行阈值(显然,选择您自己的值)。为我修复它。
  • @tinita 该文档在this section 中有一个设置宽度的参考,没有明确说明。当然,如果您以前(或在 PyYAML 中)使用 safe_load() 的关键字参数,您可以将该关键字设置为 YAML() 实例上的属性,文档中给出的一般解释也适用于此。
  • @DaveWalker 如果frame - Trigger.jpg 的路径确实只有 21 个字符,则不需要将其设置为 240。
  • @Anthon 谢谢,它实际上是一条更长的路径(更像是约 100 个字符),但为了清晰/简洁,这里减少了。 240 似乎是一个不错的圆形数字,不是出于任何特定原因而选择的。
【解决方案3】:

你可以试试 str(frame_path)

data[filename] = [{'video': video_path}, {'key_frame': str(frame_path)}, {'processed': get_timestamp()}]

【讨论】:

  • 不幸的是没有什么不同——结果完全一样。
  • 只是为了添加,还尝试使用来自 ruamel 的DoubleQuotedScalarString,它在第一行的末尾和第二行的开头明确包含 \(反斜杠)换行符。使用SingleQuotedScalarString 会按预期添加单引号,但仍会在“ - ”之前添加换行符。
  • @DaveWalker - 不确定这是否有帮助,但可以试试这个:添加“|”或 '>' 在路径中的 '-' 之前 frame_path = '/Users/xyz/imgOutput/frame |- Trigger.jpg' or frame_path = '/Users/xyz/imgOutput/frame >- Trigger.jpg'
猜你喜欢
  • 2021-08-03
  • 1970-01-01
  • 1970-01-01
  • 2014-06-12
  • 1970-01-01
  • 2015-04-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多