python - 如何在 Python 字符串模板类上转义 $?

标签 python string try-catch

介绍

string 模块有一个 Template 类,它允许您使用映射对象在字符串中进行替换,例如:

>>> string.Template('var is $var').substitute({'var': 1})
'var is 1'

例如,如果尝试替换映射中缺少的元素,替换方法可能会引发 KeyError 异常

>>> string.Template('var is $var and foo is $foo').substitute({'var': 1})
KeyError: 'foo'

或者如果模板字符串无效,则可能引发 ValueError,例如它包含一个 $ 字符后跟一个空格:

>>> string.Template('$ var is $var').substitute({'var': 1})
ValueError: Invalid placeholder in string: line 1, col 1

问题

给定一个模板字符串和一个映射,我想确定模板中的所有占位符是否都将被替换。为此,我会尝试进行替换并捕获任何 KeyError 异常:

def check_substitution(template, mapping):
    try:
        string.Template(template).substitute(mapping)
    except KeyError:
        return False
    except ValueError:
        pass
    return True

但这不起作用,因为如果模板无效并引发 ValueError,则不会捕获后续的 KeyError:

>>> check_substitution('var is $var and foo is $foo', {'var': 1})
False
>>> check_substitution('$ var is $var and foo is $foo', {'var': 1})
True

但我不关心 ValueErrors。那么,解决这个问题的正确方法是什么?

最佳答案

The docs say你可以替换模式,只要它包含所有必要的命名组:

import re
from string import Template


class TemplateIgnoreInvalid(Template):
    # override pattern to make sure `invalid` never matches
    pattern = r"""
    %(delim)s(?:
      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
      (?P<named>%(id)s)      |   # delimiter and a Python identifier
      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
      (?P<invalid>^$)            # never matches (the regex is not multilined)
    )
    """ % dict(delim=re.escape(Template.delimiter), id=Template.idpattern)


def check_substitution(template, **mapping):
    try:
        TemplateIgnoreInvalid(template).substitute(mapping)
    except KeyError:
        return False
    else:
        return True

测试

f = check_substitution
assert f('var is $var', var=1)
assert f('$ var is $var', var=1)
assert     f('var is $var and foo is $foo', var=1, foo=2)
assert not f('var is $var and foo is $foo', var=1)
assert     f('$ var is $var and foo is $foo', var=1, foo=2)
assert not f('$ var is $var and foo is $foo', var=1)
# support all invalid patterns
assert f('var is $var and foo is ${foo', var=1)
assert f('var is $var and foo is ${foo', var=1, foo=2) #NOTE: problematic API
assert     f('var is $var and foo is ${foo and ${baz}', var=1, baz=3)
assert not f('var is $var and foo is ${foo and ${baz}', var=1)

它适用于分隔符 ($) 的所有无效出现。

示例表明忽略无效模式会隐藏模板中的简单拼写错误,因此它不是一个好的 API。

关于python - 如何在 Python 字符串模板类上转义 $?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12768107/

相关文章:

python - 有没有办法在 PRINT 语句内部编写 FOR 循环?

python - 右侧带有计数器气泡的 GTK MenuItem

python - 如何在散点图上设置渐进颜色?

c++ - strcmp() 可以在 C++ 中处理字符串吗?

python - 我如何复制此 try/except 代码中的所有其他输入?

java - 抛出 IllegalArgumentException 不起作用

python - 如何在python中查找文件系统类型

java - Spring JsonDeserializer 不适用于 String 类型

string - string(int),string(int32)和string([] int32)均有效,但string([] int)无效-这里的原理是什么?

r - 在R中带有警告的函数中抑制,记录和返回值