python-3.x - 包含“ - ”的字符串总是用 ruamel.yaml 换行
问题描述
在 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 的大卖关键是人类可读的文件,很高兴了解导致它的原因以及如何修复它。
解决方案
在 YAML 中,纯标量(即没有单引号或双引号的标量)可以包装到空白处的缩进换行符。这就是正在发生的事情。
重现这一点很困难,因为您的问题非常不完整,但是从输出中可以很容易地看到一些事情:
data
是一个dict
filename
,video_path
, 和frame_path
被定义为字符串。file_handle
可能是一些为写入而打开的文件流。
其他的则不太容易推断:
get_timestamp()
不会datetime.datetime()
像人们期望的那样从它的名称返回一个实例,而是它的一个字符串表示。为了防止这个字符串被解释为时间戳,它必须被引用。- 您正在使用默认
YAML()
实例(等于typ='rt'
),因为非默认实例会以流样式(- {video: /Users/xyz/video.mp4}
等)编写叶映射
有了它和适当import
的 s 你可以制作一个正常运行的程序:
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 比您在此处显示的要长得多,并且您没有 user xyz
。这会导致您超过默认宽度(在发射器中定义为 be 80
)和要换行的普通标量。只需设置 yaml.width = 4096
标量长度和嵌套深度所需的任何内容。
当怀疑 YAML 输出是否正确时,将其读回(使用 YAML(typ='safe').load(input_stream)
,它应该会生成原始数据。
推荐阅读
- sas - 从 SAS 数据集的开头和结尾提取可变数量的列
- scala - 如何使用 circe 将密封特征案例对象转换为字符串
- numpy - 有没有办法在一个批处理操作中从一个 2D numpy 数组中切出多个 2D numpy 数组?
- javascript - 我无法使用 Redux Hooks 从 Redux 更新状态
- deployment - 需要IP才能连接Zeit上的自定义域名
- javascript - Bootstrap Tour - 强制悬停在元素上
- laravel - 自定义生成密钥的 Laravel 加密错误
- python - Pyinstaller onedir 选项 - 目录外的 exe 文件
- c++ - 引入 ofstream 时 C++ 数据文件读取不正确?
- python - 如何在字符串搜索中使用“查找”来定位搜索结果左侧的起始位置