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

Discussion in 'Python' started by Gobo Borz, Jun 25, 2003.

  1. Gobo Borz

    Gobo Borz Guest

    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
     
    Gobo Borz, Jun 25, 2003
    #1
    1. Advertising


  2. >>> Gobo Borz wrote

    > 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
     
    Anthony Baxter, Jun 25, 2003
    #2
    1. Advertising

  3. Gobo Borz

    Alan Kennedy Guest

    Gobo Borz wrote:

    > 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,

    --
    alan kennedy
    -----------------------------------------------------
    check http headers here: http://xhaus.com/headers
    email alan: http://xhaus.com/mailto/alan
     
    Alan Kennedy, Jun 25, 2003
    #3
  4. Gobo Borz

    Andy Jewell Guest

    On Wednesday 25 Jun 2003 5:20 pm, Gobo Borz wrote:
    > 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
     
    Andy Jewell, Jun 25, 2003
    #4
  5. Gobo Borz

    Gobo Borz Guest

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

    --Gobo


    Gobo Borz wrote:
    > 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
    >
     
    Gobo Borz, Jun 25, 2003
    #5
  6. Gobo Borz

    Gobo Borz Guest

    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

    wrote:
    > In article <>, Gobo Borz wrote:
    >
    >>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
    >
     
    Gobo Borz, Jun 25, 2003
    #6
  7. Gobo Borz

    Gerrit Holl Guest

    Gobo Borz wrote:
    > 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.

    --
    196. If a man put out the eye of another man, his eye shall be put out.
    -- 1780 BC, Hammurabi, Code of Law
    --
    Asperger Syndroom - een persoonlijke benadering:
    http://people.nl.linux.org/~gerrit/
    Het zijn tijden om je zelf met politiek te bemoeien:
    http://www.sp.nl/
     
    Gerrit Holl, Jun 25, 2003
    #7
  8. Gobo Borz

    Max M Guest

    #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())

    print '<a href="%(id)s">%(title)s</a> <i>%(now)s</i>' % view
    >>> <a href="42">THE TITLE</a> <i>03:06:26 00-12-16</i>
     
    Max M, Jun 25, 2003
    #8
  9. Gobo Borz wrote:

    > 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
     
    Thomas =?ISO-8859-15?Q?G=FCttler?=, Jun 26, 2003
    #9
  10. [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!

    --
    Fran├žois Pinard http://www.iro.umontreal.ca/~pinard
     
    =?iso-8859-1?q?Fran=E7ois_Pinard?=, Jun 26, 2003
    #10
  11. Adrien Di Mascio wrote:

    > 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>
     
    Fredrik Lundh, Jun 26, 2003
    #11
  12. Gobo Borz

    Chuck Spears Guest

    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")
     
    Chuck Spears, Jun 26, 2003
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    0
    Views:
    670
  2. Delaney, Timothy C (Timothy)

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

    Delaney, Timothy C (Timothy), Jun 26, 2003, in forum: Python
    Replies:
    0
    Views:
    665
    Delaney, Timothy C (Timothy)
    Jun 26, 2003
  3. Peter Bencsik
    Replies:
    2
    Views:
    839
  4. Steven D'Aprano
    Replies:
    0
    Views:
    99
    Steven D'Aprano
    Dec 23, 2013
  5. Replies:
    2
    Views:
    56
    Mark H Harris
    May 13, 2014
Loading...

Share This Page