Использовать Python f-строки с файлами Yaml?
Если у меня есть файл yaml, содержащий строку с нотацией в скобках {}, используемую совместно с f-строками python, как можно использовать здесь интерполяцию f-строки? Возьмем, к примеру, этот простой файл yaml:
# tmp.yaml
k1: val1
k2: val2 as well as {x}
Если x = 'val3'
Я хотел бы, чтобы значение k2 отражало val2 as well as val3
# app.py
x = 'val3'
with open('tmp.yaml', 'rt') as f:
conf = yaml.safe_load(f)
print(conf)
{'k1': 'val1', 'k2': 'val2 as well as {x}'}
Это может быть сделано довольно легко с форматными строками...
print(conf['k2'].format(x=x))
val2 as well as val3
Но как сделать то же самое с f-струнами?
3 ответа
Я нашел это jinja2
предоставляет самое простое решение этой проблемы.
Исходный файл yaml:
# tmp.yaml
k1: val1
k2: val2 as well as {{ x }}
Прочтите файл и выполните рендеринг с использованием шаблона jinja:
with open('tmp.yaml', 'rt') as f:
conf = f.read().rstrip()
print(conf)
# 'k1: val1\nk2: val2 as well as {{ x }}'
import jinja2
template = Template(conf)
conf = template.render(x='val3')
config = yaml.safe_load(conf)
print(config)
# {'k1': 'val1', 'k2': 'val2 as well as val3'}
Вы можете определить собственный конструктор:
import yaml
values = { 'x': 'val3' }
def format_constructor(loader, node):
return loader.construct_scalar(node).format(**values)
yaml.SafeLoader.add_constructor(u'!format', format_constructor)
conf = yaml.safe_load("""
k1: val1
k2: !format val2 as well as {x}
""")
print(conf)
Если вы не хотите использовать тег !format
Вы также можете использовать add_constructor
с u'tag:yaml.org,2002:str'
как тег Это заменит строковый конструктор по умолчанию на ваш.
Учитывая вышеупомянутые ответы, все из которых хороши, существует пакет Python для интеллектуального создания объектов из YAML / JSON / dicts, который активно разрабатывается и расширяется. (полное раскрытие, я являюсь соавтором этого пакета , см. здесь )
Кроме того, есть варианты передачи аргументов, см. Это
Затем вы можете определить это в своем YAML:
some_field: _|arg_name|_
И загрузите это так:
test_conf_yaml = PickleRick('./tests/placebos/test_config.yaml', arg_name='hallo world')
Установить:
pip install pickle-rick
Использовать:
Определите строку (или файл) YAML или JSON.
BASIC:
text: test
dictionary:
one: 1
two: 2
number: 2
list:
- one
- two
- four
- name: John
age: 20
USERNAME:
type: env
load: USERNAME
callable_lambda:
type: lambda
load: "lambda: print('hell world!')"
datenow:
type: lambda
import:
- "from datetime import datetime as dd"
load: "lambda: print(dd.utcnow().strftime('%Y-%m-%d'))"
test_function:
type: function
name: test_function
args:
x: 7
y: null
s: hello world
any:
- 1
- hello
import:
- "math"
load: >
def test(x, y, s, any):
print(math.e)
iii = 111
print(iii)
print(x,s)
if y:
print(type(y))
else:
print(y)
for i in any:
print(i)
Затем используйте его как объект.
>> from pickle_rick import PickleRick
>> config = PickleRick('./config.yaml', deep=True, load_lambda=True)
>> config.BASIC.dictionary
{'one' : 1, 'two' : 2}
>> config.BASIC.callable_lambda()
hell world!
Вы можете определять функции Python, загружать дополнительные данные из других файлов или REST API, переменных среды, а затем снова записывать все в YAML или JSON.
Это особенно хорошо работает при создании систем, требующих структурированных файлов конфигурации, или в записных книжках в виде интерактивных структур.
Это примечание по безопасности. Загружайте только те файлы, которым вы доверяете, так как любой код может быть выполнен, поэтому избегайте простой загрузки чего-либо, не зная, каково полное содержимое.
Пакет называется PickleRick и доступен здесь: