3

I'm trying to make my Python script stream its output to my webpage as its printed.

So in my javascript I do:

var xmlhttp;
var newbody = "";
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState==3) {
      newbody = newbody + xmlhttp.responseText;
      document.getElementById("new").innerHTML=newbody;
    }
}
xmlhttp.open("GET","http://localhost/cgi-bin/temp.py",true);
xmlhttp.send();

and in my Python script I have:

print "Content-Type: text/plain"
print ""
print " " * 5000   # garbage data for safari/chrome
sys.stdout.flush()

for i in range(0,5):
    time.sleep(.1)
    sys.stdout.write("%i " % i)
    sys.stdout.flush()

Now I expect 0 1 2 3 4, but what I get is 0 0 1 0 1 2 0 1 2 3 0 1 2 3 4

It seems to be sending the whole buffer each time, when what I really want is for it to send one digit per onreadystatechange.

What am I doing wrong?

Jeff
  • 12,147
  • 10
  • 51
  • 87
  • Have you tried to run it without the `sys.stdout.flush()` under the loop? If so, what was the result? – brandizzi Jun 13 '11 at 19:19
  • @brandizzi if i run it without stdout.flush(), the output is correct but it doesn't actually stream the data. it just waits for the program to finish. – Jeff Jun 13 '11 at 19:21

1 Answers1

3

xmlhttp.responseText on the client side always contains the entire response, so you don't need newbody, just use xmlhttp.responseText.

Tamás
  • 47,239
  • 12
  • 105
  • 124
  • Tamas, I know, that's the problem. How can I get xmlhttp.responseText to only contain the new portion? – Jeff Jun 13 '11 at 19:26
  • Sorry, I misunderstood your response a bit, though the problem still remains. But what you're saying is that it's a javascript problem and not a python problem, which is informative. – Jeff Jun 13 '11 at 19:30
  • You can't, this is how ``responseText`` should work - it must always contain the entire response received so far. (See http://www.w3.org/TR/2006/WD-XMLHttpRequest-20060405/#dfn-responsetext). – Tamás Jun 13 '11 at 19:31
  • Yes, it is entirely OK on the Python side. On the JS side, it would be enough to replace ``innerHTML`` with ``xmlhttp.responseText`` in order to show the output as the Python script prints it -- although I'm not sure whether anything guarantees that you will see multiple state changes to ``readyState=3`` and not just only one. – Tamás Jun 13 '11 at 19:32
  • this is just an example script; i'm actually sending back lots of json data. so my worry was 1) overhead, as i will be sending lots of data and 2) parsing, because i need to some calculations with each chunk that gets passed back. it appears #1 is not really a problem, and i believe i can solve #2 by simply keeping track of the position of responseText on each call (setting pos to responseText.length and then using responseText.substr(pos) on the next call). Thanks! – Jeff Jun 13 '11 at 19:40