如何解决如何使用 ruamel.yaml 读/写 Markdown yaml frontmatter?
我想用Python来读写markdown文件中的YAML frontmatter。我遇到了 ruamel.yaml 包,但无法理解如何为此目的使用它。
---
car:
make: Toyota
model: Camry
---
# My Ultimate Car Review
This is a good car.
首先,有没有办法在我的 python 代码中将 yaml 数据设置为变量?
第二,有没有办法给markdown文件中的yaml设置新的值?
首先,我尝试过:
from ruamel.yaml import YAML
import sys
f = open("cars.txt","r+") # I'm really not sure if r+ is ideal here.
yaml = YAML()
code = yaml.load(f)
print(code['car']['make'])
ruamel.yaml.composer.ComposerError: expected a single document in the stream
in "cars.txt",line 2,column 1
but found another document
in "cars.txt",line 5,column 1
第二,我尝试过:
from ruamel.yaml import YAML
import sys
f = open("cars.txt","r+") # I'm really not sure if r+ is ideal here.
yaml = YAML()
code = yaml.load(f)
code['car']['model'] = 'Sequoia'
ruamel.yaml.composer.ComposerError: expected a single document in the stream
in "cars.txt",column 1
解决方法
当您在一个文件中有多个 YAML 文档时,这些文档会用一行分隔:
三个破折号,或以三个破折号开头,后跟一个空格。
大多数 YAML 解析器,包括 ruamel.yaml
要么期望单个文档文件(使用 YAML().load()
时)
或多文档文件(使用 YAML().load_all()
时)。
方法 .load()
返回单个数据结构,如果似乎有多个,则会报错
文档(即当它遇到文件中的第二个 ---
时)。这
.load_all()
方法可以处理一个或多个 YAML 文档,但总是返回
一个迭代器。
您的输入恰好是一个有效的多文档 YAML 文件,但 Markdown 部分通常使情况并非如此。很容易就能
通过将第二个 ---
更改为 --- |
从而使
降价部分(多行)文字标量字符串。我不知道为什么
这种 YAML frontmatter 格式的设计者没有指定,它可能必须
这样做一些解析器(如 PyYAML)无法解析这种非缩进的文字标量
根级别的字符串正确,尽管这些示例在 YAML 中
规范。
在你的例子中,markdown 部分非常简单,它是有效的 YAML,没有
必须为文字标量字符串指定 |
。所以你可以使用
.load_all()
在此输入上。但只是添加例如一条线
以破折号开始到降价部分,将导致无效的 YAML
文档,所以如果你使用 .load_all()
,你必须确保你
不要迭代到解析第二个文档:
import sys
from pathlib import Path
import ruamel.yaml
path = Path('cars.txt')
yaml = ruamel.yaml.YAML()
for data in yaml.load_all(path):
break
print(data['car']['make'])
给出:
Toyota
您不应该尝试更新文件(所以不要使用 r+
),因为您的 YAML 前端可能是
比原来更长,并且更新会覆盖您的降价。为了
更新,将文件读入内存,根据第二行分成两部分
破折号,更新数据,转储它并附加破折号和降价:
import sys
from pathlib import Path
import ruamel.yaml
path = Path('cars.txt')
opath = Path('cars_out.txt')
yaml_str,markdown = path.read_text().lstrip().split('\n---',1)
yaml_str += '\n' # re-add the trailing newline that was split off
yaml = ruamel.yaml.YAML()
yaml.explicit_start = True
data = yaml.load(yaml_str)
data['car']['year'] = 2003
with opath.open('w') as fp:
yaml.dump(data,fp)
fp.write('---')
fp.write(markdown)
sys.stdout.write(opath.read_text())
给出:
---
car:
make: Toyota
model: Camry
year: 2003
---
# My Ultimate Car Review
This is a good car.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。