在文件中存储带有函数调用的f-string



我将函数调用的f字符串存储在一个单独的文件中(有很多变量)。

我正在写一个脚本,其中有数百个变量,然后加载到一个HTML表。HTML表中的一些内容需要调用函数。

如此:

def add_one(a):
return a + 1
a = 1
s = f"A is {a} and next comes {add_one(a)}"
print(s)

当我在一个文件中存储s时,我可以使用**locals()来格式化它,当我在s.txt中存储变量时,它可以工作。

s.txt目录:

A is {a}

有效的脚本内容:

a = 1
print(open('s.txt').read().format(**locals()))

然而,当我尝试调用函数时,它不起作用:

s.txt目录:

A is {a} and next comes {add_one(a)}

不能运行的脚本内容:

def add_one(a):
return a + 1
a = 1
print(open('s.txt').read().format(**locals()))

我能做些什么来使它工作(给定我的实际情况是数百个函数调用,而不是这个简单的2个变量的例子)?

在这个例子中,结果应该是A is 1 and next comes 2

如果您有一个包含数百个变量的复杂HTML表,您可能需要考虑使用模板语言而不是f-strings。例如Jinja2。

为了简单起见,我将a值存储在字典中,因为这样可以简化将其传递给Jinja2渲染并将其转换为JSON以将其存储在文件中。

下面是使用Jinja2模板并将数据存储到json文件的示例:

import json
from pathlib import Path
import jinja2
json_file = Path('/tmp/test_store.json')
jinja_env = jinja2.Environment()
# Set variable values
values = {'a': 3}
# Save to json file
json_file.write_text(json.dumps(values))
# Read from json file to dictionary with new variable name
read_values = json.loads(json_file.read_text())

def add_one(a):
return a + 1

# Add custom filter to jinja environment
jinja_env.filters['add_one'] = add_one
# Define template
template = jinja_env.from_string("A is {{a}} and next comes {{a | add_one}}")
# Print rendered template
print(template.render(read_values))

输出如下:

A is 3 and next comes 4

JSON文件如下:

{"a": 3}

正如在讨论中所提到的,例如这里,您想要的并不是以任何简单的方式真正工作。有一个明显的解决方法:在文本文件中存储一个f字符串(例如f"A is {a} and next comes {add_one(a)}"),然后对其进行eval:

with open('s.txt', 'r') as f:
print(eval(f.read()))  # A is 1 and next comes 2
当然,所有关于搬起石头砸自己脚的警告都适用于此,但是您的问题定义听起来与此用例完全相同。您可以尝试对函数进行沙盒之类的操作,但通常效果不佳。我想说这仍然是一个可行的自制自动化用例,但它有一个巨大的潜在的适得其反,我建议它的唯一原因是因为替代解决方案可能是危险的。

使用序列化和反序列化来存储数据

import json
data = {
"a" : 1,
"b" : 2,
"name" : "Jack",
"bunch_of_numbers" : [1, 2, 3, 5, 6]
}
file_name = "s.txt"
with open(file_name, 'w') as file:
file.write(json.dumps(data)) #serialization
with open(file_name, 'rb') as file:
data = json.load(file) # de-serialization
print(data)
输出:

{'a': 1, 'b': 2, 'name': 'Jack', 'bunch_of_numbers': [1, 2, 3, 5, 6]}

最新更新