Как заменить значение переменной окружения в файле yaml для анализа с помощью скрипта Python

1

Мне нужно использовать переменную среды "PATH" в файле yaml, которая должна обрабатываться скриптом.

Это переменная среды, которую я установил на моем терминале:

$ echo $PATH
/Users/abc/Downloads/tbwork

Это мой пример.yml:

---
Top: ${PATH}/my.txt
Vars:
- a
- b

Когда я разбираю этот файл yaml с помощью своего сценария, я не вижу фактического значения переменных PATH.

Это мой сценарий:

import yaml
import os
import sys

stream = open("sample.yml", "r")
docs = yaml.load_all(stream)
for doc in docs:
    for k,v in doc.items():
        print k, "->", v
    print "\n",

Выход:

Top -> ${PATH}/my.txt
Vars -> ['a', 'b']

Ожидаемый результат:

Top -> /Users/abc/Downloads/tbwork/my.txt
Vars -> ['a', 'b']

Может ли кто-нибудь помочь мне понять правильный способ сделать это, если я делаю это неправильно?

  • 1
    Я думаю, что вы смешиваете YAML со скриптом bash. Нет? Если вы хотите сделать это, вам придется оценить строку в терминальной среде или использовать re module, чтобы выяснить, есть ли env vars, и заменить их с помощью os.environ .
  • 0
    YAML не поддерживает такую интерполяцию строк. может быть, взглянуть на шаблонизатор Jinja2, или аналогичный?
Показать ещё 3 комментария
Теги:
python-2.7
pyyaml

1 ответ

3
Лучший ответ

Библиотека PY-yaml по умолчанию не разрешает переменные среды. Вам нужно определить неявный резольвер, который найдет регулярное выражение, определяющее переменную окружения, и выполнит функцию для ее устранения.

Вы можете сделать это через yaml.add_implicit_resolver и yaml.add_constructor. В приведенном ниже коде вы определяете распознаватель, который будет соответствовать переменной $ {env} в значении YAML и вызывает функцию path_constructor для поиска переменной окружения.

import yaml
import re
import os

path_matcher = re.compile(r'\$\{([^}^{]+)\}')
def path_constructor(loader, node):
  ''' Extract the matched value, expand env variable, and replace the match '''
  value = node.value
  match = path_matcher.match(value)
  env_var = match.group()[2:-1]
  return os.environ.get(env_var) + value[match.end():]

yaml.add_implicit_resolver('!path', path_matcher)
yaml.add_constructor('!path', path_constructor)

data = """
env: ${VAR}/file.txt
other: file.txt
"""

if __name__ == '__main__':
  p = yaml.safe_load(data)
  print(os.environ.get('VAR')) ## /home/abc
  print(p['env']) ## /home/abc/file.txt
  • 1
    Никогда не предлагайте использовать load() (прочитайте документацию, если вы не знаете почему), когда это не нужно (почти всегда). Всегда используйте safe_load() в примерах.
  • 0
    Чтобы использовать safe_load() мне пришлось изменить вышеописанное, например, так ... yaml.add_implicit_resolver('!path', path_matcher, None, SafeLoader) yaml.add_constructor('!path', path_constructor, SafeLoader)
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню