You can use the standard library string and its Template class.
Given an input file foo.txt:
$title
$subtitle
$list
And this code in example.py:
from string import Template
d = {
'title': 'This is the title',
'subtitle': 'And this is the subtitle',
'list': '\n'.join(['first', 'second', 'third'])
}
with open('foo.txt', 'r') as f:
src = Template(f.read())
result = src.substitute(d)
print(result)
Then run it:
$ python example.py
This is the title
And this is the subtitle
first
second
third
Answer from ThibThib on Stack OverflowYou can use the standard library string and its Template class.
Given an input file foo.txt:
$title
$subtitle
$list
And this code in example.py:
from string import Template
d = {
'title': 'This is the title',
'subtitle': 'And this is the subtitle',
'list': '\n'.join(['first', 'second', 'third'])
}
with open('foo.txt', 'r') as f:
src = Template(f.read())
result = src.substitute(d)
print(result)
Then run it:
$ python example.py
This is the title
And this is the subtitle
first
second
third
There are quite a number of template engines for python: Jinja, Cheetah, Genshi etc. You won't make a mistake with any of them.
python - advanced string formatting vs template strings - Stack Overflow
python - String replace templating utility - Code Review Stack Exchange
python how to convert from string.template object to string - Stack Overflow
How to save String Template as a Text file in Python 3? - Stack Overflow
One key advantage of string templates is that you can substitute only some of the placeholders using the safe_substitute method. Normal format strings will raise an error if a placeholder is not passed a value. For example:
"Hello, {first} {last}".format(first='Joe')
raises:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'last'
But:
from string import Template
Template("Hello, $first $last").safe_substitute(first='Joe')
Produces:
'Hello, Joe $last'
Note that the returned value is a string, not a Template; if you want to substitute the $last you'll need to create a new Template object from that string.
Templates are meant to be simpler than the the usual string formatting, at the cost of expressiveness. The rationale of PEP 292 compares templates to Python's %-style string formatting:
Python currently supports a string substitution syntax based on C's
printf()'%' formatting character. While quite rich, %-formatting codes are also error prone, even for experienced Python programmers. A common mistake is to leave off the trailing format character, e.g. thesin%(name)s.In addition, the rules for what can follow a % sign are fairly complex, while the usual application rarely needs such complexity. Most scripts need to do some string interpolation, but most of those use simple "stringification" formats, i.e.
%sor%(name)sThis form should be made simpler and less error prone.
While the new .format() improved the situation, it's still true that the format string syntax is rather complex, so the rationale still has its points.
Python has a number of templating options, but the simplest to start is probably the string.Template one described in https://docs.python.org/3/library/string.html#template-strings
This supports targets such as $StockId and is used as below
>>> from string import Template
>>> s = Template('$who likes $what')
>>> s.substitute(who='tim', what='kung pao')
'tim likes kung pao'
If you need more output options, look at the string.format functionality, but this is probably best for starting with.
Style
Python has a style guide called PEP8. Among many other great things, it gives guidelines about spacing that you do not follow. Indeed, your spacing seems to be quite inconsistent. You'll find tools such as pep8 to check your compliancy to PEP8 and other tools such as ``autopep8 to fix your code automatically.
It can be a good habit to move the part of your program doing things (by opposition to the part of your program defining things) behind an if __name__ == "__main__" guard.
You can also use tools such as pylint to check your code. Among other things, Python naming convention are now followed.
Don't repeat yourself / avoid magic numbers
I can see 30 in multiples places. This is usually a bad sign : if you ever want to change the value to something else, you'll have to change it in multiple places. You probably should define a constant to hold that value behind a meaningful name.
Even better, you could define a function to perform the particular behavior that you want :
Getting the length the right way
At the moment, you are keeping track of the number of rows in input_file by incrementing a variable x. It is much clearer to simply use len(intput_file). Also, x = x + 1 can simply be written : x += 1.
Taking these various comments into account, you get :
import csv
SIZE_LINE = 30
def print_with_line(s):
print(s)
print('-' * SIZE_LINE)
if __name__ == '__main__':
# Open template file and pass string to 'data'.
# Should be in HTML format except with string replace tags.
with open('testTemplate.htm', 'r') as my_template:
data = my_template.read()
# print template for visual cue.
print_with_line('Template passed:')
print_with_line(data)
# open CSV file that contains the data and
# store to a dictyionary 'input_file'.
with open('test1.csv') as csv_file:
input_file = csv.DictReader(csv_file)
for row in input_file:
# create filenames for the output HTML files
filename = 'listing' + row['stockID'] + '.htm'
# print filenames for visual cue.
print(filename)
# create output HTML file.
with open(filename, 'w') as output_file:
# run string replace on the template file
# using items from the data dictionary
# HELP--> this is where I get nervous because
# chaos will reign if the tags get mixed up
# HELP--> is there a way to add identifiers to
# the tags? like %s1 =row['stockID'], %s2=row['color'] ... ???
output_file.write(data % (
row['stockID'],
row['color'],
row['material'],
row['url']))
# print the number of files created as a cue program has finished.
print_with_line(str(len(input_file)) + ' files created.')
safe_substitute returns, as a string, the template with the substitutions made. This way, you can reuse the same template for multiple substitutions. So your code has to be
print html.safe_substitute(toFirstName='jibin',fromFirstName='Vishnu')
According to the docs you should take the return Value of safe_substitute
fp = open(r'D:\UserManagement\invitationTemplate.html', 'rb')
html = Template(fp.read())
fp.close()
result = html.safe_substitute(toFirstName='jibin',fromFirstName='Vishnu')
print result
Python foundation just accepted PEP 750 for template strings, or called t-strings. It will come with Python 3.14.
There are already so many methods for string formatting in Python, why another one??
Here is an article to dicsuss its usefulness and motivation. What's your view?