string.template 仅做纯文本替换,不执行表达式,比 % 和 f-string 更安全,适合处理用户输入模板;使用 $name 或 ${name} 占位符,推荐 safe_substitute() 防 keyerror。

string.Template 的基本用法和安全优势
直接用 string.Template 替换字符串,比用 % 格式化或 f-string 更安全——它不执行任意表达式,只做纯文本替换,适合处理用户输入的模板(比如邮件模板、配置片段)。核心是定义带 $ 前缀的占位符,再调用 substitute() 或 safe_substitute()。
常见错误:写成 ${name} 却传入 dict(name=...) 没问题,但若漏掉 name 键,substitute() 会抛 KeyError;而 safe_substitute() 会保留原占位符(如 $name)不报错。
- 占位符支持两种写法:
$name和${name},后者在占位符后紧跟字母/数字时必须用大括号,例如${user}id - 要转义
$字符本身,写成$$ - 不能嵌套表达式,
${2 * x}或${data['key']}都无效,会原样输出
如何传参:字典、关键字参数、对象属性
substitute() 接收字典、关键字参数,或任何带 __getitem__ 方法的对象(比如自定义类)。但注意:它**不支持点号访问属性**,$user.name 是非法的,会当作一个叫 user.name 的键去查。
示例场景:从 API 返回的 JSON 数据生成日志消息,字段可能缺失。
from string import Template
t = Template("Hello, $name! Your balance: $balance")
# 安全替换,字段缺失也不崩
result = t.safe_substitute(name="Alice", extra="ignored") # → "Hello, Alice! Your balance: $balance"
- 推荐优先用
safe_substitute()处理不可控输入 - 传字典时用
**d解包,如t.substitute(**data_dict) - 想支持
$obj.field这种写法?得自己实现__getitem__解析点号,Template原生不支持
自定义分隔符:改掉 $ 符号
如果模板里本来就有很多 $(比如 shell 脚本、正则表达式),默认分隔符会冲突。这时可以继承 Template 并重写 delimiter 类属性。
注意:修改分隔符后,所有占位符必须严格匹配新符号,且不能与原有文本逻辑混淆。
from string import Template
<p>class PercentTemplate(Template):
delimiter = '%'</p><p>t = PercentTemplate("Price: %price, Tax: %tax")
result = t.substitute(price=100, tax=8) # → "Price: 100, Tax: 8"</p>
- 只能改分隔符,不能同时支持多种分隔符
- 分隔符只能是单字符,不能设成
%%或{% - 改了
delimiter后,idpattern(标识符匹配规则)可能也要同步调整,否则%123这类会被忽略
和 f-string、.format() 的关键区别在哪
别把它当成“轻量版 f-string”——string.Template 的设计目标就是**隔离逻辑与文本**。它不解析表达式、不支持格式说明符(如 :.2f)、不调用方法($user.upper() 无效),所以性能略高,但功能也更受限。
典型误用:试图用它做数值格式化或条件拼接。这时候该换 str.format() 或 jinja2 等模板引擎。
-
f-string:适合代码内动态拼接,强类型、快,但不安全、不可复用模板字符串 -
str.format():支持位置/关键字、格式说明符、简单表达式({x*2}),但仍有执行风险 -
string.Template:仅变量替换,无逻辑,适合模板由非开发者提供、或需多次复用同一模板的场景
真正容易被忽略的是:它对空格敏感——$ name 中的空格会被当作键名一部分,查不到就留空或报错。写模板时多检查下占位符前后有没有意外空格。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











