From: Santiago Caracol on
Hello,

I want to write a web application that does this:

(1) The user submits a query:

---------------------------------
| What is the answer? |
---------------------------------
<Submit>

(2) The web server gives the user N answers and a button saying "More
answers":

.. answer 1
.. answer 2
.. answer 3

<More answers>

I am aware of several ways to do this: I could calculate all
answers, but show only the first N of them. For certain kinds of
calulations,
I could use a kind of setoff argument. But I would like to do it in a
more general
and (hopefully) efficient way:

I want the function or object that calculates the answers to be
"frozen" at the point at which it has already calculated N answers. If
the function gets a <More answers>-signal within a reasonable period
of time, it goes on producing more answers exactly at the point at
which it got frozen. If no signal is sent, the function call is
terminated automatically after
M seconds.

Note that, although the program to be written is a web application,
this is not a question about web application specific things. My only
difficulty is how to "freeze" function calls.

Has anyone done something of this kind?

Santiago
From: Peter Otten on
Santiago Caracol wrote:

> Hello,
>
> I want to write a web application that does this:
>
> (1) The user submits a query:
>
> ---------------------------------
> | What is the answer? |
> ---------------------------------
> <Submit>
>
> (2) The web server gives the user N answers and a button saying "More
> answers":
>
> . answer 1
> . answer 2
> . answer 3
>
> <More answers>
>
> I am aware of several ways to do this: I could calculate all
> answers, but show only the first N of them. For certain kinds of
> calulations,
> I could use a kind of setoff argument. But I would like to do it in a
> more general
> and (hopefully) efficient way:
>
> I want the function or object that calculates the answers to be
> "frozen" at the point at which it has already calculated N answers. If
> the function gets a <More answers>-signal within a reasonable period
> of time, it goes on producing more answers exactly at the point at
> which it got frozen. If no signal is sent, the function call is
> terminated automatically after
> M seconds.
>
> Note that, although the program to be written is a web application,
> this is not a question about web application specific things. My only
> difficulty is how to "freeze" function calls.
>
> Has anyone done something of this kind?

Python offers an elegant mechanism to calculate values on demand: the
generator function:

>>> def calculate_answers():
.... for i in range(100):
.... print "calculating answer #%d" % i
.... yield i * i
....
>>> from itertools import islice
>>> gen = calculate_answers()

This builds the generator but doesn't run the code inside. Now let's look at
the first three "answers":

>>> for answer in islice(gen, 3):
.... print "the answer is", answer
....
calculating answer #0
the answer is 0
calculating answer #1
the answer is 1
calculating answer #2
the answer is 4

If you repeat the last step you get the next three answers:

>>> for answer in islice(gen, 3):
.... print "the answer is", answer
....
calculating answer #3
the answer is 9
calculating answer #4
the answer is 16
calculating answer #5
the answer is 25

Peter
From: Santiago Caracol on
> Python offers an elegant mechanism to calculate values on demand: the
> generator function:
>
> >>> def calculate_answers():
>
> ...     for i in range(100):
> ...             print "calculating answer #%d" % i
> ...             yield i * i
> ...
>

Thanks for pointing this out. I was aware of the yield statement.

My problem is this:

(1) The user submits a query:

---------------------------------
| What is the answer? |
---------------------------------
<Submit>

(2) The web server gives the user N answers and a button saying "More
answers":

.. answer 1
.. answer 2
.. answer 3

<More answers>

At this stage the function that writes html to the user has been
called. The call must be terminated, or else, the user doesn't get any
html. This means that the call of the answer-calculating function,
whether it uses yield or not, is also terminated. This means, when the
user presses the <More answers>-button, the calculation has to start
at the beginning.

From: Peter Otten on
Santiago Caracol wrote:

>> Python offers an elegant mechanism to calculate values on demand: the
>> generator function:
>>
>> >>> def calculate_answers():
>>
>> ... for i in range(100):
>> ... print "calculating answer #%d" % i
>> ... yield i * i
>> ...
>>
>
> Thanks for pointing this out. I was aware of the yield statement.
>
> My problem is this:
>
> (1) The user submits a query:
>
> ---------------------------------
> | What is the answer? |
> ---------------------------------
> <Submit>
>
> (2) The web server gives the user N answers and a button saying "More
> answers":
>
> . answer 1
> . answer 2
> . answer 3
>
> <More answers>
>
> At this stage the function that writes html to the user has been
> called. The call must be terminated, or else, the user doesn't get any
> html. This means that the call of the answer-calculating function,
> whether it uses yield or not, is also terminated. This means, when the
> user presses the <More answers>-button, the calculation has to start
> at the beginning.

Adapted from the wsgiref documentation at

http://docs.python.org/library/wsgiref.html

$ cat wsgi_demo.py
from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server

from itertools import count, islice

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

gen = answers()

def simple_app(environ, start_response):
setup_testing_defaults(environ)

status = '200 OK'
headers = [('Content-type', 'text/plain')]

start_response(status, headers)

return islice(gen, 3)

httpd = make_server('', 8000, simple_app)
print "Serving on port 8000..."
httpd.serve_forever()

Run the above with

$ python wsgi_demo.py
Serving on port 8000...

Now point your favourite browser to http://localhost:8000/ and hit refresh.

Peter
From: Santiago Caracol on
> 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.

Santiago


 |  Next  |  Last
Pages: 1 2
Prev: Checker 1.3 Released!
Next: Weird Python behaviour