pythonstringtemplate

How to specify a default value for unspecified variable in Python string templates?


Consider the following code

from string import Template
s = Template('$a $b')

print(s.safe_substitute(a='hello'))  # $b is not substituted
print(s.substitute(a='hello'))  # raise error

What I want is that I can specified a default value for all the unspecified variables in the template, for example, an empty string ''.

The reason I need this feature is there is a case that both template and variables are provided by users. They may provided some placeholders in the template string as an injection point in case someone else may need to use them, but if the user don't provide value for it those placeholders should be ignore. And I don't need to specify different default values for different variables, but just a common default value for all missing variables.

I don't have to stick to the string template module, but I don't want to use heavy solution like jinja2 either. I just want to have a lightweight template soltuion to get things done.

The method to provide a default dictionary doesn't work in my case as the template is provided by other users, so I don't know the possbile vaiables before hand.


Solution

  • As stated in documentation, safe_substitute and substitute accept values in 2 forms - as keyword arguments, as you are doing, or as a mapping dict. It also assures us that "When both mapping and kwds are given and there are duplicates, the placeholders from kwds take precedence". With this in mind, we can use this mapping dict to provide default values for all variables, and ones we pass explicitly as keyword will get overwritten with new values.

    from string import Template
    s = Template('$a $b')
    
    
    defaults = {'a': 'a_default', 'b': 'b_default'}
    
    print(s.safe_substitute(defaults, a='hello'))  # hello b_default
    print(s.substitute(defaults, a='hello'))  # hello b_default
    

    If all the identifiers should use same default value, you can use a defaultdict with the same method.

    from string import Template
    from collections import defaultdict
    s = Template('$a $b')
    
    defaults = defaultdict(lambda: '')
    
    print(s.safe_substitute(defaults, a='hello'))  # $b is not substituted
    print(s.substitute(defaults, a='hello'))  # raise error