1

I'm trying to create an HTML file, which certains Python variables that have to be evaluated. My code looks like this:

name = ['Nora', 'John', 'Jack', 'Jessica']

html = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Names</title>
</head>
<body>
    <ul>
        <li>Mother: <%= name[0] %></li>
        <li>Father: <%= name[1] %></li>
        <li>Son: <%= name[2] %></li>
        <li>Daughter: <%= name[3] %></li>
    </ul>
</body>
</html>
"""

Html_file = open("names.html","w")
Html_file.write(html)
Html_file.close()

However, the array is not interpreted during output. My HTML source looks like this:

...
<ul>
    <li>Mother: <%= name[0] %></li>
    <li>Father: <%= name[1] %></li>
    <li>Son: <%= name[2] %></li>
    <li>Daughter: <%= name[3] %></li>
</ul>
...

How can I evaluate the python code that's surrounded by <%= %>?

1
  • 1
    You're building a static string html but you're never combining this with your array names. There are several ways to do this, search for string formatting. Commented Mar 14, 2018 at 11:03

4 Answers 4

1

There're multiple ways of achieving this

First off, if you're on Python 3.6 or higher, there's a new syntax called f-string, which is basically a method of string formatting at run time.

name = ['Nora', 'John', 'Jack', 'Jessica']

html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Names</title>
</head>
<body>
    <ul>
        <li>Mother: {name[0]}</li>
        <li>Father: {name[1]}</li>
        <li>Son: {name[2]}</li>
        <li>Daughter: {name[3]}</li>
    </ul>
</body>
</html>
"""

print(html)

The way you use f-string is fairly easy, add an f in the beginning of the string, and use { } instead of <%= %>.


If you're on any Python version, or wanted a version-compatible method, there are many other ways of string interpolation (ie. C-style string formatting %, Python string formatting .format(), and string concatenation), one of which (.format()) is in the other answers.


Without changing your HTML: using re and eval

If you don't have control over where you got the "need-to-be-substituted" html, or if you have to use the <%= %> scheme, you can simply use a combination of re and eval:

from re import sub


name = ['Nora', 'John', 'Jack', 'Jessica']

html = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Names</title>
</head>
<body>
    <ul>
        <li>Mother: <%= name[0] %></li>
        <li>Father: <%= name[1] %></li>
        <li>Son: <%= name[2] %></li>
        <li>Daughter: <%= name[3] %></li>
    </ul>
</body>
</html>
"""

html = sub(r"<%=\s*(\S+)\s*%>", lambda l: eval(l.group(1)), html)

print(html)
Sign up to request clarification or add additional context in comments.

1 Comment

The f-string is perfect for me. Thank you!
0

A string won't automatically evaluate code inside, but you can achieve this in a handful of ways:

Introduce placeholders and format your string:

name = ['Nora', 'John', 'Jack', 'Jessica']

html = """
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Names</title>
</head>
<body>
    <ul>
        <li>Mother: {0}</li>
        <li>Father: {1}</li>
        <li>Son: {2}</li>
        <li>Daughter: {3}</li>
    </ul>
</body>
</html>
"""

Html_file = open("names.html","w")
Html_file.write(html.format(name[0], name[1], name[2], name[3])
Html_file.close()

This is a very simple way to do it. There are more advanced approaches, such as using a template engine. Here you can read more about them.

Comments

0
    html = """<ul>
        <li>Mother:  {0} </li>
        <li>Father:  {1} </li>
        <li>Son: {2} </li>
        <li>Daughter: {3} </li>
        </ul>"""
    name = ['Nora', 'John', 'Jack', 'Jessica']
    print(html.format(*name))
    >>><ul>
        <li>Mother: Nora </li>
        <li>Father: John </li>
        <li>Son: Jack </li>
        <li>Daughter: Jessica </li>
       </ul>

2 Comments

I don't think he wants the <%= and %> to appear in the html.
@Constance you're right.. I have edited my answer. thanks for pointing it out.
0

You can use regex to more accurately evaluate the templating:

import re
name = ['Nora', 'John', 'Jack', 'Jessica']
def render_template(html, **kwargs):
  return re.sub('\<%\=\s[a-zA-Z]+\[\d+\]\s%\>', '{}', html).format(*[kwargs.get(re.findall('[a-zA-Z]+', i)[0])[int(re.findall('\d+', i)[0])] for i in re.findall('(?<=\<%\=\s)[a-zA-Z]+\[\d+\](?=\s%)', html)])

print(render_template(html, name = name))

Output:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Names</title>
</head>
<body>
<ul>
    <li>Mother: Nora</li>
    <li>Father: John</li>
    <li>Son: Jack</li>
    <li>Daughter: Jessica</li>
  </ul>
</body>
</html>

This solution will also work if name elements are being accessed in random order:

html = """
<body>
  <ul>
    <li>Mother: <%= name[3] %></li>
    <li>Father: <%= name[1] %></li>
    <li>Son: <%= name[0] %></li>
    <li>Daughter: <%= name[2] %></li>
 </ul>
</body>
"""
print(render_template(html, name = name))

Output:

<body>
  <ul>
   <li>Mother: Jessica</li>
   <li>Father: John</li>
   <li>Son: Nora</li>
   <li>Daughter: Jack</li>
</ul>
</body>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.