better way than: myPage += 'more html' , ...

G

Gobo Borz

Hi everyone,

I have a python cgi program that uses print statements to write html.
The program has grown, and for reasons I won't bore you with, I need to
build the page in a string and "print" it at once.

I remember reading somewhere that building the string with successive
"+=" statements is inefficient, but I don't know any alternatives, and
my search attempts came up empty. Is there a better, more efficient way
to do it than this:

#---------------------------------
htmlPage = "<html><header></header><body>"
htmlPage += "more html"
....
htmlPage += "even more html"
....
htmlPage += "</body></html>"
print htmlPage
#-------------------------------------

Thanks, Gobo
 
A

Anthony Baxter

I remember reading somewhere that building the string with successive
"+=" statements is inefficient, but I don't know any alternatives, and
my search attempts came up empty. Is there a better, more efficient way
to do it than this:

#---------------------------------
htmlPage = "<html><header></header><body>"
htmlPage += "more html"
...
htmlPage += "even more html"
...
htmlPage += "</body></html>"
print htmlPage
#-------------------------------------

Instead, build up a list of strings, then join them all at
the end - this way, the system only has to allocate the
space once. Much quicker.

#---------------------------------
htmlPage = []
htmlPage.append("<html><header></header><body>")
htmlPage.append("more html")
...
htmlPage.append("even more html")
...
htmlPage.append("</body></html>")
page = ''.join(htmlPage)
print page
#-------------------------------------

Anthony
 
A

Alan Kennedy

Gobo said:
I remember reading somewhere that building the string with successive
"+=" statements is inefficient, but I don't know any alternatives, and
my search attempts came up empty. Is there a better, more efficient way
to do it than this:

#---------------------------------
htmlPage = "<html><header></header><body>"
htmlPage += "more html"
...
htmlPage += "even more html"
...
htmlPage += "</body></html>"
print htmlPage
#-------------------------------------

Best to do something like

#---------------------------------

htmlbits = []
htmlbits.append("<html><header></header><body>")
htmlbits.append("more html")
# ...
htmlbits.append("even more html")
# ...
htmlbits.append("</body></html>")

# And now for the non-intuitive bit
print "".join(htmlbits)

#---------------------------------

HTH,
 
A

Andy Jewell

Hi everyone,

I have a python cgi program that uses print statements to write html.
The program has grown, and for reasons I won't bore you with, I need to
build the page in a string and "print" it at once.

I remember reading somewhere that building the string with successive
"+=" statements is inefficient, but I don't know any alternatives, and
my search attempts came up empty. Is there a better, more efficient way
to do it than this:

#---------------------------------
htmlPage = "<html><header></header><body>"
htmlPage += "more html"
...
htmlPage += "even more html"
...
htmlPage += "</body></html>"
print htmlPage
#-------------------------------------

Thanks, Gobo


An easy way, which requires little changes tou your code would be to use a
list and join it up into a string in one go at the end:

-----------8<--------------
htmlPage=["<html><header></header><body>\n"]
htmlPage.append("more html\n")
....
htmlPage.append("more html\n")
....
htmlPage.append("<\body><\html>\n")
htmlDoc="".join(htmlPage)
-----------8<--------------

This is more efficient, as the string joining is done all at the same time,
rather than in little chunks.

hope that helps
-andyj
 
G

Gobo Borz

Thanks Alan, Anthony, and Andy! B's thru Z's need not respond, I have
my answer.

--Gobo
 
G

Gobo Borz

Thanks, that opens up a world of possibilities I haven't began to
explore. In general, I'm not fond of templating systems because of the
overhead, but it seems as your suggestion might be fast, since it uses
ordinary string substitution.

--Gobo

I remember reading somewhere that building the string with successive
"+=" statements is inefficient, but I don't know any alternatives, and
my search attempts came up empty. Is there a better, more efficient way
to do it than this:

#---------------------------------
htmlPage = "<html><header></header><body>"
htmlPage += "more html"
...
htmlPage += "even more html"
...
htmlPage += "</body></html>"
print htmlPage
#-------------------------------------

Hello Gobo,

you may use the list solution provided in the former chapters. Some other
solution would be to use string substitution:
--------- snip -----------
htmlPage = """
<html>
<head>
<title>%(title)s</title>
</head>
<body>
<h1>%(title)s</h1>
%(body)s
</body>
</html>
"""

body = []
body.append("<p>my first snippet</p>")
body.append("<ul>")
for in range(10):
body.append("""<li>%s. entry</li>""" % i)
body.append("</ul>")

contents = { "title": "My Foopage",
"body": "\n".join(body) }

print htmlPage % contents
-------- snap -------------

This type of substitution goes for a very simple templating system.

Best Regards
Mirko
 
G

Gerrit Holl

Gobo said:
I have a python cgi program that uses print statements to write html.
The program has grown, and for reasons I won't bore you with, I need to
build the page in a string and "print" it at once.

Another way, which has not yet been mentioned but which I like much,
is the cStringIO module. You can write to a string as if it is a
file:

0 >>> import cStringIO
1 >>> mystr = cStringIO.StringIO()
2 >>> mystr.write("<html")
3 >>> mystr.write("<body>")
4 >>> mystr.write("<h1>Header</h1>")
5 >>> mystr.write("<p>Hello, world!</p>")
6 >>> mystr.write("</body></html>")
10 >>> mystr.getvalue()
'<html<body><h1>Header</h1><p>Hello, world!</p></body></html>'

The cStringIO module is documented at:

http://www.python.org/dev/doc/devel/lib/module-StringIO.html

cStringIO is a faster C implementation with the same API.

yours,
Gerrit.
 
M

Max M

#Gobo Borz wrote:
#> Thanks, that opens up a world of possibilities I haven't began to
#> explore. In general, I'm not fond of templating systems because of the
#> overhead, but it seems as your suggestion might be fast, since it uses
#> ordinary string substitution.
#

Often an adapter is a good choice:


class HtmlViewAdapter:

"""
Base class that Adapts any object to html output.
"""

def __init__(self, obj):
self._obj = obj

def __getattr__(self, attr):
"Returns values for the attributes"
return getattr(self._obj, attr)

def __getitem__(self, item):
"get attrs as items for use in string formatting templates"
value = getattr(self, item)
if callable(value):
return value()
else:
return value

import time

class SomeObject:

"The object we want displayed in html"


def __init__(self):
self.id = 42
self.now = time.localtime()
self.title = 'the title'



class SomeObjectHtmlView(HtmlViewAdapter):

"""
an adapter for the object, here you can fine adjust, format dates
etc.
"""

def title(self):
return self._obj.title.upper()

def now(self):
return time.strftime('%y:%m:%d %H-%M-%S',self._obj.now)


view = SomeObjectHtmlView(SomeObject())

 
T

Thomas =?ISO-8859-15?Q?G=FCttler?=

Gobo said:
Hi everyone,

I have a python cgi program that uses print statements to write html.
The program has grown, and for reasons I won't bore you with, I need to
build the page in a string and "print" it at once.

Hi!

I do it like this:

def foo(mydict):
ret=[]

rows=[]
for key, value in mydict.items():
rows.append('<tr><td>%s</td><td>%s</td></tr>' % (key, value))
rows=''.join(rows)

ret.append('<table>%s</table>' % rows)
return ''.join(ret)

I try to keep the start-tag and the end-tag in one string.
This keeps the code from becomming ugly.

thomas
 
?

=?iso-8859-1?q?Fran=E7ois_Pinard?=

[Max M]
I remember reading a post where I saw meassurements that showed it to be
twice as fast. I was too lazy too google it. But here goes. [...]

[Adrien Di Mascio]
I've a made a quite basic test on these methods : [...]

Thanks to both! Have a good day!
 
F

Fredrik Lundh

Adrien said:
I've a made a quite basic test on these methods :

/snip/

def write_thousands_join(self, char):
"""Writes a 100000 times 'char' in a list and joins it
"""
str_list = []
for index in range(100000):
str_list.append(char)

return ''.join(str_list)

no time to repeat your tests, but

def write_thousands_join(self, char):
"""Writes a 100000 times 'char' in a list and joins it
"""
str_list = []
append = str_list.append # bind method to local variable
for index in range(100000):
append(char)

return ''.join(str_list)

"should" be slightly faster.

also note that the results "may" differ somewhat if you append strings
of different lengths (mostly due to different overallocation strategies;
or maybe they're not different anymore; cannot remember...)

I always use join, but that's probably because that method is more likely
to run code that I once wrote. Never trust code written by a man who
uses defines to create his own C syntax ;-)

</F>
 
C

Chuck Spears

I have a question with regards to the sprintf style of replacing
strings. I have a table in my HTML with a 50% width specifier. How
can i get the formatter to ignore it. For example in the example
below how can i code the 50% to be ignored?

keep the "%s 50% %s" % ("a","b")
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top