如何使用Yaml文件和Python f字符串?

5

如果我有一个包含使用大括号符号{}与python f-strings配合使用的字符串的yaml文件,我该如何在此处利用f-string插值?以这个简单的yaml文件为例:

# tmp.yaml
k1: val1
k2: val2 as well as {x}

如果x = 'val3',我希望k2的值反映val2以及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-strings实现相同的功能呢?

看不出这是一个重复项。你能详细说明一下吗? - user9074332
1
我认为这是不可能的。使用.format() :) - Nic
@user9074332 YAML最接近的功能是使用锚点和引用(在链接的问题中有描述)。 - wim
2个回答

3

您可以定义自定义构造函数:

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_constructoru'tag:yaml.org,2002:str'作为标签。这将用您的构造函数覆盖默认的字符串构造函数。


请问您能提供一些背景信息吗? - user9074332
1
@user9074332 发生的情况是,您将本地标签 !format 放在 YAML 标量 val2 as well as {x} 上,然后告诉 PyYAML:“当您遇到一个带有 !format 标记的节点时,请使用此函数从中构造目标值”。在该函数中,您首先使用 PyYAML 的常规构造函数构造一个字符串,然后调用 format,并提供包含要执行的替换的 value 字典。您也可以只使用 ...format(x='val3'),但我展示的方法可以推广到具有多个替换模板的较大的 YAML 文件。 - flyx

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'}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接