能否用PyYAML来读取里面写有 "YAML前置事项 "块的文本文件?

问题描述 投票:2回答:2

很抱歉,我对YAML和PyYAML都知之甚少,但我觉得很喜欢支持用 "Jekyll "所使用的相同风格来编写配置文件的想法(http:/jekyllrb.comdocsfrontmatter),AFAIK有这些 "YAML Front Matter "块,在我看来非常酷,非常性感。所以我在我的电脑上安装了PyYAML,我写了一个小文件,里面有这个文本块。

---
First Name: John
Second Name: Doe
Born: Yes
---

Lorem ipsum dolor sit amet, consectetur adipiscing elit,  
sed do eiusmod tempor incididunt ut labore et dolore magna  
aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco 
laboris nisi ut aliquip ex ea commodo consequat.

然后我试着用Python 3. 4和PyYAML用这段代码来读取这个文本文件。

import yaml

stream = open("test.yaml")
a = stream.read()
b = yaml.load(a)

但很明显这行不通,Python显示了这个错误信息。

Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    b = yaml.load(a)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/yaml/__init__.py", line 72, in load
    return loader.get_single_data()
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/yaml/constructor.py", line 35, in get_single_data
    node = self.get_single_node()
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/yaml/composer.py", line 43, in get_single_node
    event.start_mark)
yaml.composer.ComposerError: expected a single document in the stream
  in "<unicode string>", line 2, column 1:
    First Name: John
    ^
but found another document
  in "<unicode string>", line 5, column 1:
    ---
    ^

你能帮帮我吗?是我的代码写错了,还是说PyYAML不能处理YAML前事项块?我还可以尝试用PyYAML做什么,或者我必须使用regex写我自己的解析器吗?

非常感谢您的时间!

python yaml pyyaml
2个回答
9
投票

的Python yaml 库不支持读取嵌入文档中的yaml。这里有一个实用函数可以提取yaml文本,这样你就可以在读取文件的剩余部分之前对其进行解析。

#!/usr/bin/python2.7

import yaml
import sys

def get_yaml(f):
  pointer = f.tell()
  if f.readline() != '---\n':
    f.seek(pointer)
    return ''
  readline = iter(f.readline, '')
  readline = iter(readline.next, '---\n')
  return ''.join(readline)


for filename in sys.argv[1:]:
  with open(filename) as f:
    config = yaml.load(get_yaml(f))
    text = f.read()
    print "TEXT from", filename
    print text
    print "CONFIG from", filename
    print config

3
投票

你可以在没有任何自定义解析的情况下,通过调用 yaml.load_all() 来代替。这将返回一个生成器,其中第一项是作为 dict 的预期的前端内容,第二项是作为字符串的文档的其余部分。

import yaml

with open('some-file-with-front-matter.md') as f:
    front_matter, content = list(yaml.load_all(f, Loader=yaml.FullLoader))[:2]

如果你只想要前面的内容,那就更简单了:

import yaml

with open('some-file-with-front-matter.md') as f:
    front_matter = next(yaml.load_all(f, Loader=yaml.FullLoader))

这样做的原因是 yaml.load_all() 是用于在同一个文档中加载多个YAML文档。,界线为 ---. 另外,从未知来源加载YAML时,一定要采取通常的预防措施。

EDIT: 更新了代码,包括一个 Loader 争论 现在需要并更新了文档链接。同时也验证了该代码即使在 --- 的内容中,根据下面的评论。

© www.soinside.com 2019 - 2024. All rights reserved.