2015-08-12 3 views
3

У меня есть YAML файл (all.yaml), который выглядит следующим образом:нагрузки YAML вложен Jinja2 в Python

... 
var1: val1 
var2: val2 
var3: {{var1}}-{{var2}}.txt 
... 

Если я загрузить его в Python, как это:

import yaml 

f = open('all.yaml') 
dataMap = yaml.safe_load(f) 
f.close() 
print(dataMap["var3"]) 

выход {{var1}}-{{var2}}.txt и не val1-val2.txt.

Возможно ли заменить вложенные вары на значение?

Я пытался загрузить его с:

import jinja2 
templateLoader = jinja2.FileSystemLoader(searchpath="/path/to/dir") 
templateEnv = jinja2.Environment(loader=templateLoader) 
TEMPLATE_FILE = "all.yaml" 
template = templateEnv.get_template(TEMPLATE_FILE) 

Исключение больше не кинули, теперь я застрял и должны исследовать, как поступить.

+0

Вы, очевидно, нужно будет использовать jinja2 в какой-то момент. что ты уже испробовал? – larsks

+0

я пытался загрузить его с импорта Jinja2 templateLoader = jinja2.FileSystemLoader (SearchPath = "/") templateEnv = jinja2.Environment (Загрузчик = templateLoader) файла_с_шаблоном = "all.yaml" шаблон = templateEnv.get_template (файла_с_шаблоном) но это бросит TemplateNotFound-Exception –

+0

Лучше обновить свой ответ, а не пытаться оставить образцы кода в комментариях. Исключение 'TemplateNotFound' должно быть относительно легко разрешено; маловероятно, чтобы ваши файлы 'all.yml' находились в'/', но именно там вы сказали Jinja2 посмотреть. – larsks

ответ

-2

В спецификации YAML нет замены/замены скалярных частей.

Все, что вы хотите сделать на этом уровне, должно быть выполнено в вашем приложении. Для меня, и для YAML, {{var1}} - это всего лишь вложенное сопоставление. {{var1}} не подходит для {{var1: null}: null}. После этого не допускается -.

Есть однако несколько проблем с вашим постом:

  1. Вы используете PyYAML, который поддерживает только старый (2005) YAML 1.1. Поэтому вы не можете вы не можете иметь несколько документов (т.е. закончилась ...) без использования явного начала документа (---), как вы можете в YAML 1,2

  2. Даже если вы исправите первую строку прочитать --- вместо ... вашего файла будет не загружайте в Словаре {{var1}} не может сопровождаться скаляр - (от -{{var2}}.txt)

  3. и если бы вы просто использовать {{var1}} в файле, PyYAML не может загрузить это, как он загружает YAML отображения, как Python Dict и Python не разрешить изменяемые ключи для dict. Так же, как вы получите TypeError в Python, когда вы пытаетесь сделать: {dict(var1=None): None}

Таким образом, вы должны, по крайней мере, изменить входной файл all.yaml на:

--- 
var1: val1 
var2: val2 
var3: '{{var1}}-{{var2}}.txt' 
... 

, чтобы получить это, чтобы загрузить в YAML.

Вы должны загрузить этот файл, два раза:

  • один раз PyYAML, чтобы получить значение, которые можно использовать для визуализации шаблона
  • раз в качестве шаблона по Jinja2

После вы визуализируете шаблон, который вы загружаете (строка) еще раз в PyYAML, и у вас есть значение, которое вы хотите.

Учитывая исправленное all.yaml, как указано выше в текущем каталоге и этой программы:

import yaml 
import jinja2 

YAML_FILE = 'all.yaml' 
with open(YAML_FILE) as fp: 
    dataMap = yaml.safe_load(fp) 

env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath='.')) 
template = env.get_template(YAML_FILE) 

data = yaml.safe_load(template.render(**dataMap)) 
print(data["var3"]) 

будет печатать то, что вы хотите:

val1-val2.txt 
+0

Вы можете абсолютно комбинировать модуль YAML и модуль Jinja2, чтобы сделать что-то вроде того, что спрашивает OP. [Ansible] (http://ansible.com) - один из примеров инструмента, который выполняет обработку шаблонов Jinja2 по значениям YAML. Так что конечно, вы не можете сделать это с помощью модуля 'yaml', но я не думаю, что это то, о чем спрашивает OP. – larsks

+0

@larsks Ваш комментарий полностью упускает из виду, что, когда я писал свой ответ, OP только пытался загрузить это с помощью YAML и ожидал, что для расширения переменных. Посмотрите на историю, прежде чем вы сделаете (неинформированное) решение. – Anthon

0

Вот один из возможных решений:

  1. Анализ вашего документа YAML с помощью модуля yaml
  2. Итерации по ключам в документе YAML, рассматривая каждое значение как шаблон Jinja2, в который вы передаете ключи документа YAML в качестве параметров.

Например:

import yaml 
from jinja2 import Template 

with open('sample.yml') as fd: 
    data = yaml.load(fd) 

for k, v in data.items(): 
    t = Template(v) 
    data[k] = t.render(**data) 

print yaml.safe_dump(data, default_flow_style=False) 

Это будет прекрасно работать с конкретным примером, но ничего полезного, скажем, вложенных структур данных не будет делать (на самом деле, это, вероятно, просто взрывают) ,

+0

Когда файл YAML содержит что-то вроде * val: 1.5 * он будет вызывать AttributeError: объект «float» не имеет атрибута «iter_fields» –

+0

О, абсолютно. Это пример, а не надежное решение! :) – larsks

0

Я не верю, что вы можете использовать yaml.load или yaml.safe_load в файле, содержащем переменные jinja2, в качестве значений. {{Variable}} будет пытаться интерпретироваться как dict by yaml.

0

Сначала определите класс Undefined и загрузите yaml, чтобы получить известные значения. Затем загрузите его снова и произведите с известными значениями.

#!/usr/bin/env python 

import yaml 
from jinja2 import Template, Undefined 

str1 = '''var1: val1 
var2: val2 
var3: {{var1}}-{{var2}}.txt 
''' 

class NullUndefined(Undefined): 
    def __getattr__(self, key): 
    return '' 

t = Template(str1, undefined=NullUndefined) 
c = yaml.safe_load(t.render()) 

print t.render(c) 

Выполнить это:

$ ./test.py 
var1: val1 
var2: val2 
var3: val1-val2.txt 

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

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