Forum Moderators: coopster & phranque

Message Too Old, No Replies

Print before script has finished a foreach loop

How do I do it ?

         

Damian

3:35 pm on Feb 3, 2002 (gmt 0)

10+ Year Member



I'm trying to figure out how to print results from a foreach statement line by line, as opposed to waiting untill the loop is completed and printing all lines.
Ie., i'd like to say something like

[perl]
foreach $item (@items) {
# do something with $item
print "$item\n";
}
[/perl]

..and see my screen fill up line by line, instead of waiting untill the loop is finished and then seeing all lines at once. Does anyone know how I can do that ?

Brett_Tabke

8:28 pm on Feb 3, 2002 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Put the text into a variable and then print the variable after the loop. You can use the concatenation operator to connect the text to the variable as you run through the loop.

foreach $item (@items) {
# do something with $item
$stuff.="$item\n";
}
print $stuff;

The .= is the concatenation operator that adds the text to the end of the current variable. It is just another way of saying:

foreach $item (@items) {
# do something with $item
$stuff = $stuff . "$item\n";
}

You can also use it to do expressions:

$total+=12; #add 12 to $total.
$total-=5; #subtract 12 to total.

bird

8:48 pm on Feb 3, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Put the text into a variable and then print the variable after the loop.

If I understand Damian correctly, that's exactly the opposite of what he wants, and gives the same result he currently sees with his own implementation.

Most likely, the problem is caused by the default stream buffering. You can cause each new text to be displayed in the browser immediately (well, to be sent to it immediately, anyway), by setting your stdout channel to unbuffered.

As even looking at Perl code gives me headaches very quickly, someone else will have to tell you how to do that in Perl... ;)

Brett_Tabke

9:00 pm on Feb 3, 2002 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Yes, I did misread it. I saw the example and thought he wanted the opposite. Add the following to unbuffer the output near the top of the script.

$¦++;

Damian

9:01 pm on Feb 3, 2002 (gmt 0)

10+ Year Member



Thanks guys. What bird said..I want it to print each line immediately as the loop takes a long time to complete.
stdout and buffers...I heard about those before and know I can't eat them ..
Back to the books.

bird

9:04 pm on Feb 3, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



$¦++;

What did I say about headaches? ;)

Though the wrapping thread option links below are a powerful medicine, thanks!

Damian

10:00 pm on Feb 3, 2002 (gmt 0)

10+ Year Member



I tried that at the top of the script, and to be sure just above and within the foreach loop, but it doesn't seem to work ?

Here's what I used for a test..where urls.txt is a large file (120.000 lines). I noticed lines will be printed in chunks with or without the $¦++; , but only after the script has finished.
[perl]
#!F:\perl\bin\perl.exe
########################
$¦++;
open(FILE,"<urls.txt");
while($line = <FILE>){$lines .= $line;}
close(FILE);

@urls = "$lines";
foreach $req (@urls) {
print "URL: $req<br>";
}
exit;

[/perl]

Brett_Tabke

10:12 pm on Feb 3, 2002 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



Then your web server is the one buffering the output. Not much you can do. It can be very tricky to isolate which one is doing it.
Apache or iis?

Damian

10:14 pm on Feb 3, 2002 (gmt 0)

10+ Year Member



Win32 Apache for development..will go to Unix/Apache later when it goes live.

littleman

10:42 pm on Feb 3, 2002 (gmt 0)



I believe you have to nph (non parse header) the script for apache to turn off it's buffering. That means you will have to do your own headers. Try doing a search here for 'nph' to find some examples.

bird

10:50 pm on Feb 3, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I believe you have to nph

This only used to be necessary before Apache 1.3. Is the Windows version really that outdated?

I rather suspect the broken pipe implementation in Windows. You can flush as much as you want, and the pipe will just keep buffering. I only dealt with this in C once, and I don't remember exactly what I did to fix it. One thing to try might be to set the stdout stream to binary mode. Can't garantee that this will help, but trying won't hurt... ;)

Damian

11:00 pm on Feb 3, 2002 (gmt 0)

10+ Year Member



Thanks all. Renaming the little example script above to nph-test.cgi did it :)

Edit: sorry, I was too fast, that didn't do it. I'll do some more experimenting and report if I find a solution.

btherl

9:09 am on Feb 13, 2002 (gmt 0)

10+ Year Member



g'day damian :) (can you guess who I am?)

I had a lot of fun with this while trying to get a browser not to time out while doing some processing.. the following script seems to work with the following server:

Server: Apache/1.3.22 (Unix) Debian GNU/Linux PHP/4.1.1 mod_auth_pam/1.0a mod_ssl/2.8.5 OpenSSL/0.9.6c mod_perl/1.26

The script:


use CGI;

$¦++;

my $q = new CGI;
print $q->header('text/plain');

my $i = 99;
while ($i) {
print "$i green bottles on the wall..\n";
$i--;
sleep(1);
}

In IE 5.5 it starts displaying at 91 bottles, and works fine after that. In Mozilla 0.9.7 it starts at 98 bottles. It's running under mod_perl.. not sure if that makes a difference.

gethan

10:55 am on Feb 13, 2002 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



[cgiconnection.com...]

Shows you how to do all this - haven't used it myself, will have ago when I have a spare minute or two.

Note the caveat that some windows webservers don't suppport this... <snip>I think apache will be excluded as its so good ;)</snip> - not working so far

[edited]Didn't work on NT - Apache (1.3.22) - IE5.5 or Mozilla 0.9.7 - worth trying on apache linux[/edited]

Damian

11:49 am on Feb 13, 2002 (gmt 0)

10+ Year Member



> can you guess who I am
Even the server config looks familiar :)

Thanks guys, much appreciated. I was about to give up and that article is just what I was looking for.

Multipart/mixed headers...going to try those now, as I couldn't get the script to work the way I want on the unix server either.

Damian

12:38 pm on Feb 13, 2002 (gmt 0)

10+ Year Member



Tested the multipart/mixed headers, they were indeed what I needed for the Unix server. Does not work under win32 for me either though.

I tried to run Btherl's script but both my machines seem to hang on the sleep command so I can't confirm the same behaviour on my servers yet before I look into that.
Do you have an explanation for the display timing difference Btherl ? Are the 91 or 98 lines what the machine processed in the first second before it gets to the next second, then understands the sleep command and starts printing one line per second from there on ?