2

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?

Hoseong Jeon
  • 1,240
  • 2
  • 12
  • 20

4 Answers4

2

You can use some template engine that mix logic into template.

Example with jinja2:

  1. 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.

buran
  • 13,682
  • 10
  • 36
  • 61
2

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.

BoarGules
  • 16,440
  • 2
  • 27
  • 44
1

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.

Tom Wojcik
  • 5,471
  • 4
  • 32
  • 44
0

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.

U13-Forward
  • 69,221
  • 14
  • 89
  • 114