我正在尝试用Python的模板替换{{var}}
格式的变量。
from string import Template
class CustomTemplate(Template):
delimiter = '{{'
pattern = r'''
{{(?:
(?P<escaped>{{)|
(?P<named>[_a-z][_a-z0-9]*)}}|
(?P<braced>[_a-z][_a-z0-9]*)}}|
(?P<invalid>)
)
'''
replacement_dict = {
"test": "hello"
}
tpl = '''{
"unaltered": "{{foo}}",
"replaced": "{{test}}"
}'''
a = CustomTemplate(tpl)
b = a.safe_substitute(replacement_dict)
print(b)
输出:
{
"unaltered": "{{foo",
"replaced": "hello"
}
正如你所看到的,{{foo}}
变量(它不是替换的一部分)的右括号被剪掉了。我认为这是regex的编写方式(右}}
)?
我想用Template解决这个问题,而不是用任何其他外部库。
我不确定你是如何做到这一点的。在linux上,在python 3.4.3中(我以为我是在2.7的某个版本中完成的),我需要将tpl设置为字符串
tpl = '''
"unaltered": "{{foo}}",
"replaced": "{{test}}"
'''
以避免获得TypeError
>>> tpl = '''
... "unaltered": "{{foo}}",
... "replaced": "{{test}}"
... '''
>>> a = CustomTemplate(tpl)
>>> a.template
'n "unaltered": "{{foo}}",n "replaced": "{{test}}"n'
>>> b = a.safe_substitute(replacement_dict)
>>> b
'n "unaltered": "{{foo}}",n "replaced": "hello"n'
当我这样做时,{{foo}}是不变的。
我尝试了上面的代码,但看起来该代码实际上不适用于python 2.7.6。我会看看我是否能找到一种方法使它与2.7.6一起工作,因为这似乎是最近linux发行版的常见版本。
更新:
看起来这是2007年的一个已知错误。http://bugs.python.org/issue1686据我所知,它在2010年应用于python 3.2,在2014年应用于python 2.7。就实现这一点而言,您可以应用问题1686的补丁,也可以使用该补丁中的实际源代码覆盖类中的safe_substitute()https://hg.python.org/cpython/file/8a98ee6baa1e/Lib/string.py.
此代码适用于2.7.6和3.4.3
from string import Template
class CustomTemplate(Template):
delimiter = '{{'
pattern = r'''
{{(?:
(?P<escaped>{{)|
(?P<named>[_a-z][_a-z0-9]*)}}|
(?P<braced>[_a-z][_a-z0-9]*)}}|
(?P<invalid>)
)
'''
def safe_substitute(self, *args, **kws):
if len(args) > 1:
raise TypeError('Too many positional arguments')
if not args:
mapping = kws
elif kws:
mapping = _multimap(kws, args[0])
else:
mapping = args[0]
# Helper function for .sub()
def convert(mo):
named = mo.group('named') or mo.group('braced')
if named is not None:
try:
# We use this idiom instead of str() because the latter
# will fail if val is a Unicode containing non-ASCII
return '%s' % (mapping[named],)
except KeyError:
return mo.group()
if mo.group('escaped') is not None:
return self.delimiter
if mo.group('invalid') is not None:
return mo.group()
raise ValueError('Unrecognized named group in pattern',
self.pattern)
return self.pattern.sub(convert, self.template)
replacement_dict = {
"test": "hello"
}
tpl = '''{
"escaped": "{{{{",
"unaltered": "{{foo}}",
"replaced": "{{test}}",
"invalid": "{{az"
}'''
a = CustomTemplate(tpl)
b = a.safe_substitute(replacement_dict)
print (b)
结果:
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import template
{
"escaped": "{{",
"unaltered": "{{foo}}",
"replaced": "hello",
"invalid": "{{az"
}
>>>
问题
- 开发人员reggie希望使用带有python PEP292模板字符串的自定义占位符分隔符
解决方案(解决方法)
- 开发人员reggie可以更改占位符前缀字符
- 这种方法允许使用来自完全不同的编程语言的分隔符语法
- 这种方法实现了更改占位符语法的主要目的,以防止分隔符冲突问题
- 这种方法提供了对字符串进行子类化的最直接的情况。模板
陷阱
- 这种方法不支持像
{{var}}
这样的双大括号占位符 - 在开发人员无法随意更改模板语法的情况下,这种方法没有帮助
示例
导入字符串通过类TemplateRubyish(string.Template):分隔符='#'idpattern=r'[a-z][\w\,\+\=\:\-\.\x2f\x5c\*\(\)\[\]\x7c]*'class TemplatePerlish(string.Template):分隔符='qq'idpattern=r'[a-z][\w\,\+\=\:\-\.\x2f\x5c\*\(\)\[\]\x7c]*'replacement_dict={}replacement_dict.update({"年龄":"34","fname":"荷马","lname":"Simpson",});通过##vout=模板Rubyish("\问候#{fname}#{lname},你是#{age}ish岁").safe_substitute(replacement_dict);打印(vout)通过##vout=模板英语("\问候qq{fname}qq{lname},你是qq{age}ish岁").safe_substitute(replacement_dict);打印(vout)通过
结果
问候霍默·辛普森,你34岁了。问候霍默·辛普森,你34岁了。