string.template 是 python 中安全轻量的字符串模板工具,使用 $name 或 ${name} 占位,仅支持纯变量替换,不执行代码;substitute() 要求所有占位符有值,否则抛 keyerror,safe_substitute() 则保留未提供变量;它不支持属性访问(如 $user.name),需预展平数据或改用下划线命名;相比 str.format() 和 f-string,template 专为不可信输入设计,天然防注入。

string.Template 的基本用法和替换语法
string.Template 是 Python 标准库中轻量、安全的字符串模板工具,适合做纯变量替换,不执行任意代码。它用 $name 或 ${name} 作为占位符,比 % 格式化或 f-string 更严格,也更难意外触发代码执行。
最常用的是 substitute() 方法,它接受字典或关键字参数:
from string import Template
t = Template("Hello, $name! Your score is $score.")
result = t.substitute(name="Alice", score=95)
注意:substitute() 要求所有占位符都有对应值,缺一个就抛 KeyError;如果想忽略缺失变量,改用 safe_substitute(),未提供的占位符会原样保留。
处理变量名含点号、括号或下划线的场景
默认情况下,$user.email 这样的写法会被解析为变量名 user.email(含点),但 Python 变量名本身不允许点号,所以直接传 {"user.email": "a@b.com"} 是合法的——Template 不校验变量名是否符合 Python 命名规则,只做字符串匹配。
不过更常见的是想表达嵌套结构(如 ${user.name})。这时不能靠默认行为实现,因为 Template 不支持属性访问。可行做法是预处理数据:
- 手动展平:把
{"user": {"name": "Bob"}}转成{"user_name": "Bob"},再用$user_name - 用
safe_substitute()配合字典解包:先flat_dict = {f"{k}_{sk}": sv for k, v in data.items() for sk, sv in v.items()},再传入 - 避免用点号,改用下划线或连字符(如
$user_name),这是最稳妥的实践
与 str.format() 和 f-string 的关键区别在哪
核心差异不在功能强弱,而在设计目标:
-
string.Template:面向不可信输入(比如用户提交的模板字符串),禁止表达式、函数调用、索引访问等,天然防注入 -
str.format():支持{name.upper()}、{items[0]}等,但若模板来自外部,可能执行任意属性访问或方法调用 -
f-string:编译期求值,完全不适用于运行时动态模板,且无法复用同一模板多次渲染
举个实际例子:你开放一个邮件模板编辑页面,用户输入 "Hi, $name. Your balance: $amount.",后端用 Template 渲染是安全的;换成 "Hi, {name}. Your balance: {amount}." 再用 .format(**data),用户若填入 name="x.__class__.__mro__[1].__subclasses__()[0].__init__.__globals__" 就可能出问题(虽然概率低,但风险真实存在)。
常见报错和绕过方式
最常遇到的两个错误是:
-
ValueError: Invalid placeholder:占位符里用了非法字符,比如$name*、$name!。解决办法是转义:写成$$name*(第一个$被解释为字面量$,后面部分当普通文本) -
KeyError: 'xxx':substitute()找不到对应 key。别急着加 try/except,先确认传入字典的 key 类型是str(不是int或其他类型),且大小写完全一致;或者直接换用safe_substitute()
另外注意:空模板字符串 Template("") 是合法的,但 substitute() 仍会检查所有占位符——哪怕模板为空,只要里面写了 $missing,照样报 KeyError。
真正容易被忽略的是:如果你在循环中反复构建 Template 实例(比如每次请求都 Template(tpl_str)),而模板字符串不变,其实可以提前初始化一次并复用——Template 对象是线程安全的,且内部做了简单缓存,没必要每次都解析。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











