Welcome, guest | Sign In | My Account | Store | Cart

New to python 2.4 is the string.Template class. It is similar to the formatting python already had in which the % operator with strings was used in a recognizable sprintf style of formatting from C. In addition to format types, you also had a choice with a tuple or dictionary mapping. String.Template simplifies it to only the string format type and dictionary mapping. This makes string formatting easier to remember and use. This example shows you the basics of using the template and the difference with the old style.

Python, 40 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import string

#With the new style, you mark a label in a string with with a $ and use a #dictionary to map that label to something else. 

new_style=string.Template('this is $thing')
print new_style%{'thing':5}      #produces:  this is 5                              
print new_style%{'thing':'test'} #produces: this is test

#With the old style you have to specify a type as a formatting code
#in this case, %s is used for a string format. Note how the old style 
#string is not as clean looking.

old_style='this is %(thing)s'
print old_style%{'thing':5}      #produces: this is 5
print old_style%{'thing':'test'} #produces: this is test

#Here is an example that shows 3 basic uses of the new Template.
#The standard mapping with $customer, handeling of the case where characters #not part of the label directly follow it with ${name}Inn, and finally the use #of $$ to insert an actual $ into the string.

form_letter='''Dear $customer,
I hope you are having a great time.
If you do not find Room $room to your satisfaction,
let us know. Please accept this $$5 coupon.
            Sincerely,
            $manager
            ${name}Inn'''
                                        
letter_template=string.Template(form_letter)

print letter_template%{'name':'Sleepy','customer':'Fred Smith',
                       'manager':'Barney Mills','room':307,
                      }
#produces:
Dear Fred Smith,
I hope you are having a great time.
If you do not find Room 307 to your satisfaction,
let us know. Please accept this $5 coupon.
            Sincerely,
            Barney Mills
            SleepyInn

The string.Template is a welcome addition to string formatting. The older sprintf style can be tedious to remember formatting for the dictionary mapping if you do not use it often. And, if you are familar with languages like perl, string.Template will also look familar since substitution in strings in perl use the $ notation.

There is also a SafeTemplate option you can use in cases where the dictionary may not have all the labels (check the docs for how to use it since it is still not final as of the alpha version of python). And finally, in true python style, you can of course subclass String.Template to do more fancy things.

5 comments

Foo Bear 17 years, 2 months ago  # | flag

No more SafeTemplate. In the current CVS version SafeTemplate has been removed, see this: http://mail.python.org/pipermail/python-checkins/2004-September/043214.html

Nick Coghlan 17 years, 2 months ago  # | flag

String templates will not take this form in Python 2.4. Discussions on the Python development mailing list have led to changes in the structure of string templates.<p> <p> At the time of this posting, CVS uses a single Template class, with separate, standard methods that implement the operations of the Template and SafeTemplate mod operators in this recipe, but I wouldn't consider the format settled until at least the first beta.

John Nielsen (author) 17 years, 2 months ago  # | flag

Thanks. I made the change in my comments to reflect this.

John Nielsen (author) 17 years, 2 months ago  # | flag

my email is pyguy2 on yahoo. If you want to reach me (the author) you can find me at pyguy2 on yahoo

Nick Coghlan 17 years, 1 month ago  # | flag

The beta is out! Which means the Template API can now be considered stable.

A simple example of the new interface:

from string import Template
t = Template("test = $test")
test = 5

print t.substitute(locals()) # prints "test = 5"

del test

print t.safe_substitute(locals()) # prints "test = $test"
print t.substitute(locals()) # throws KeyError

And the simplest form of customisation:

from string import Template
class Percent_Template(Template):
  delimiter = '%'
  # Set idpattern to change what constitutes an 'identifier'

p = Percent_Template("test = %test")
test = 5
print p.substitute(locals()) # prints "test = 5"

It's also possible to change the pattern completely:

from string import Template
class Quote_Template(Template):
  """Substitute anything inside double quotes"""
  # Template expects four named groups in the pattern
  # We use empty named groups at the end for the
  # ones we don't need

  pattern = r"""
    "(?P.*)"   # Replace anything between double quotes
    (?P)(?P)(?P)"""

q = Quote_Template('test = "test"')
test = 5
print q.substitute(locals()) # prints "test = 5"

q = Quote_Template('tricky = "1 x z"')
print q.substitute({"1 x z" : "tricky!"})
# prints "tricky = tricky!"
Created by John Nielsen on Thu, 9 Sep 2004 (PSF)
Python recipes (4591)
John Nielsen's recipes (36)

Required Modules

  • (none specified)

Other Information and Tasks