2014-09-12 1 views
1

Прошу прощения, я очень мало знаю о YAML и PyYAML, но я влюбился в идею поддержки конфигурационного файла, написанного в том же стиле, что и «Jekyll» (http://jekyllrb.com/docs/frontmatter/), что AFAIK имеет эти «передние предметы» YAML «Блоки, которые выглядят очень здорово и сексуально для меня.
Так я установил PyYAML на моем компьютере, и я написал небольшой файл с этим блоком текста:Можно ли использовать PyYAML для чтения текстового файла, записанного внутри блока «YAML front matter» внутри?

--- 
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, или мне нужно написать собственный парсер с помощью регулярного выражения?

Большое спасибо за ваше время!

+1

Вы можете получить текст между тройными черточками и передать его загрузчику yaml. Является ли Bla blabla частью документа yaml? – user3557327

+0

Спасибо за предложение. Часть «Blabla» не YAML. В основном это текстовый файл, который имеет часть YAML в начале и нормальную часть, отличную от YAML, после трех последних тире. – Cesco

ответ

6

Библиотека Python 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 
+0

Большое спасибо за ответ – Cesco

+0

Для python3 вам нужно использовать 'readline .__ next__'. – dahrens

4

Вы можете сделать это без какого-либо пользовательского разбора по телефону yaml.load_all() вместо этого. Это возвращает генератор из которых первого элемент является ожидаемым вводным как Словарь, а второй является остальной частью документа в виде строки:

import yaml 

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

Если вы просто хотите вводное это еще проще:

import yaml 

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

Это работает, потому что yaml.load_all() is for loading several YAML documents within the same document, ограниченная ---. Кроме того, при загрузке YAML из неизвестного источника убедитесь, что вы принимаете обычные меры предосторожности.

+0

Спасибо, что нашли время ответить на мой вопрос. – Cesco

+0

Этот код сломается, если содержимое содержит '---'. Вместо этого порекомендует вместо этого ответ. – oxalorg

 Смежные вопросы

  • Нет связанных вопросов^_^