'Formatting HTML with Python
I want to format my html code in python.
My Python file is:
titles = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
html_text = """<html>
<head>
<style type="text/css">
table { border-collapse: collapse;}
td { text-align: center; border: 5px solid #ff0000; border-style: dashed; font-size: 30px; }
</style>
</head>
<body>
<table width="100%" height="100%" border="5px">
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
</table>
</body>
</html> % (titles[0], titles[1], titles[2], titles[3], titles[4])"""
f = open('temp.html', 'w')
f.write(html_text)
f.close()
I want to make those %s to be titles[0], titles[1], titles[2], titles[3], titles[4].
How can I make it?
Solution 1:[1]
There are two errors in your format string. The first, as U9-Forward pointed out, is here:
</html> % (titles[0], titles[1], titles[2], titles[3], titles[4])"""
The % is an interpolation operator so it needs to go between the string and the data:
</html>""" % (titles[0], titles[1], titles[2], titles[3], titles[4])
The second error, apparent only after you fixed that one, is here:
<table width="100%" height="100%" border="5px">
When you use the % operator, the character % becomes special, so that %s does what you expect. But when that happens, "100%" isn't legal, because, as the error message told you, it puts an unsupported format character '"' (0x22) at index 237. You could have found this out for yourself in under a minute by putting your cursor at the beginning of the string and pressing right-arrow 237 times.
In this case, the % that you want to stay % must be doubled:
<table width="100%%" height="100%%" border="5px">
That gives
html_text = '''<html>
<head>
<style type="text/css">
table { border-collapse: collapse;}
td { text-align: center; border: 5px solid #ff0000; border-style: dashed; font-size: 30px; }
</style>
</head>
<body>
<table width="100%%" height="100%%" border="5px">
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
</table>
</body>
</html>''' % (titles[0], titles[1], titles[2], titles[3], titles[4])
But the fundamental problem here is that Python %-strings are a formatting mini-language, and HTML is a formatting language, and so constructing HTML like this means you are programming in two languages simultaneously. The doublethink that this involves gives some experienced programmers a kick, but the rest of us are happier separating our concerns and dealing with one language at a time. Instead of %-strings, consider using lxml to construct your HTML. There is more of a learning curve (eased by an excellent tutorial) but your code will be easier to write and maintain, and lxml will ensure your HTML is free of syntax errors.
Solution 2:[2]
fstrings is what cool kids use nowadays.
titles = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
html_text = f"""<html>
<head>
<style type="text/css">
table {{ border-collapse: collapse;}}
td {{ text-align: center; border: 5px solid #ff0000; border-style: dashed; font-size: 30px; }}
</style>
</head>
<body>
<table width="100%" height="100%" border="5px">
<tr>
<td>{titles[0]}</td>
</tr>
<tr>
<td>{titles[1]}</td>
</tr>
<tr>
<td>{titles[2]}</td>
</tr>
<tr>
<td>{titles[3]}</td>
</tr>
<tr>
<td>{titles[4]}</td>
</tr>
</table>
</body>
</html>"""
with open('temp.html', 'w') as f:
f.write(html_text)
You put variable in {} within a text, and your styles have to be escaped with double {{}}. Try it out.
Also, pythonic way of writing to a file is with a context manager. It handles closing without the need of .close() on an opened file.
Solution 3:[3]
You can use some template engine that mix logic into template.
Example with jinja2:
- install with
pip install jinja2
2 then the code would be:
html_text = """<html>
<head>...</head>
<body>
<table width="100%" height="100%" border="5px">
{% for title in titles %}
<tr>
<td>{{title}}</td>
</tr>
{% endfor %}
</table>
</body>
</html>"""
from jinja2 import Template
titles = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
my_templ = Template(html_text)
with open('temp.html', 'w') as f:
f.write(my_templ.render(titles=titles))
Note that it is flexible to handle list of variable length. Template engines are used in the web frameworks.
Solution 4:[4]
You ended the string in the wrong place, so use the below as full code:
titles = ['aaa', 'bbb', 'ccc', 'ddd', 'eee']
html_text = '''<html>
<head>
<style type="text/css">
table { border-collapse: collapse;}
td { text-align: center; border: 5px solid #ff0000; border-style: dashed; font-size: 30px; }
</style>
</head>
<body>
<table width="100%" height="100%" border="5px">
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
<tr>
<td>%s</td>
</tr>
</table>
</body>
</html>''' % (titles[0], titles[1], titles[2], titles[3], titles[4])
f = open('temp.html', 'w')
f.write(html_text)
f.close()
So now you'll get your expected HTML file.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | BoarGules |
| Solution 2 | Tom Wojcik |
| Solution 3 | |
| Solution 4 |
