freeze function calls

Peter Otten __peter__ at web.de
Tue Aug 10 17:46:02 CEST 2010


Santiago Caracol wrote:

>> Run the above with
>>
>> $ python wsgi_demo.py
>> Serving on port 8000...
>>
> 
> Thanks a lot for this code. The problem with it is that the whole
> application IS a generator function. That means that if I run the code
> at, say foo.org, then any user that visits the site will augment the
> answer number of the server running at foo.org. What I am trying to do
> is to process specific queries for different users. Each user is
> supposed to get his very own answers to his very own questions. And if
> a user doesn't hit the <More answers>-button during a certain period
> of time, the generator or function call reponsible for answering his
> question is supposed to be killed or thrown-away or forgotten. If the
> user asks a new question (while the answers to the old question are
> still being displayed), then the generator or function call is also
> supposed to be forgotten and a new generator or function call -- one
> that matches the user's new question -- is supposed to be initiated.

Didn't you say you weren't interested in the web specific aspects?
You may be able to do it by hand (the environ argument will probably include 
an IP that you can use to look up the generator in a dictionary) but I'd 
rather say you need a web framework that provides the session management.
Cherrypy is a lightweight one, and after some try and way too much error I 
came up with

# warning: newbie code
import cherrypy
from itertools import islice, count

def answers():
    for i in count():
        yield "Answer #%d\n" % i

class PythonRunner(object):
    def index(self):
        try:
            gen = cherrypy.session["gen"]
        except KeyError:
            cherrypy.session["gen"] = gen = answers()
        return "<html><body>%s</body></html>" % "".join(islice(gen, 3))
    index.exposed = True

if __name__ == '__main__':
    cherrypy.quickstart(PythonRunner(), config="cherry.conf")

The contents of cherry.conf are:

[global]
server.socket_host = "127.0.0.1"
server.socket_port = 8080
server.thread_pool = 10

[/]
tools.sessions.on = True
#tools.sessions.storage_type = "file"
#tools.sessions.storage_path = "./sessions"
tools.sessions.timeout = 60

See the result on http://localhost:8080/index
I opened the page in Firefox and Konqueror, and the numbers were 
independent, so I'm pretty sure it works on a bigger scale, too.

$ python -c 'import cherrypy; print cherrypy.__version__'
3.1.2

Note that storage_type = "file" is straight out for generators because they 
cannot be pickled. The workaround here would be a class like

class Answers(object):
    def __init__(self):
        self.i = 0
    def __iter__(self):
        return self
    def next(self):
        result = "Answer #%d\n" % self.i
        self.i += 1
        return result

Peter



More information about the Python-list mailing list