Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I was messing around with some stuff today and noticed something that seemed odd to me but is probably known by most. I noticed that in the following code no print statements were printed to stdout until the script was completely done.
#!perl -w use strict; my $count = 0; my $times = 0; my $sec = 0; print "Doing something "; while (1) { my $time = localtime(); my @broken = split(/ /, $time); for (@broken) { $time = $1 if (/((\d+)\:(\d+)\:(\d+))/); } my @stime = split(/\:/, $time); if ($sec < $stime[2]) { $count++; } $sec = $stime[2]; if ($count == 5) { print ". "; $count = 0; $times++; } last if ($times == 12); } print " done!\n";
Now if I added a print statement anywhere in there with a newline character it printed as it went along like it is suppose to.
#!perl -w use strict; my $count = 0; my $times = 0; my $sec = 0; print "Doing something "; while (1) { my $time = localtime(); my @broken = split(/ /, $time); for (@broken) { $time = $1 if (/((\d+)\:(\d+)\:(\d+))/); } my @stime = split(/\:/, $time); if ($sec < $stime[2]) { $count++; print "Incremented count!\n"; } $sec = $stime[2]; if ($count == 5) { print ". "; $count = 0; $times++; } last if ($times == 12); } print " done!\n";
Any explanation of this behavior?

Replies are listed 'Best First'.
Re: Won't print unless newline is included?
by bmann (Priest) on Apr 27, 2004 at 22:26 UTC
Re: Won't print unless newline is included?
by Räuber Hotzenplotz (Acolyte) on Apr 27, 2004 at 22:27 UTC
    If you don't have STDOUT flushing turned on by saying
    $| = 1;
    the print statements won't flush until there's a newline.
Re: Won't print unless newline is included?
by davido (Cardinal) on Apr 27, 2004 at 23:07 UTC
    As others have mentioned, the "easiest" fix is to turn off buffering (in other words, turn on auto-flush) by giving the special variable $| a value:  $| = 1;

    But stop and consider for a moment that buffering is on by default for a reason. Turning it off will affect file IO speeds, which generally improve with buffering.

    One thing you can do is to localize the damage done by turning on autoflush. That can be done lexically as follows:

    print "Beginning test.\n"; print "This is not autoflushed..."; sleep 3; { local $| = 1; print "This is autoflushed..."; sleep 3; } print "This is not autoflushed..."; sleep 3;


    Dave

Re: Won't print unless newline is included?
by sgifford (Prior) on Apr 27, 2004 at 22:28 UTC

    That's perl's buffering. Just like the C stdio library, it buffers its output; when it's printing to the terminal it flushes the buffers every time it prints a newline character, and printing to a pipe or a file only when it finishes writes a full block of bytes. It does one final flush right before the program exits.

    The easiest way to fix this is to turn on autoflush, with this assignment: $|=1;

Re: Won't print unless newline is included?
by pizza_milkshake (Monk) on Apr 27, 2004 at 23:33 UTC
    perl uses output buffering by default, since writing to stdout is slow. add
    $| = 1;
    at the top of your script to disable output buffering.

    perl -e'$_="nwdd\x7F^n\x7Flm{{llql0}qs\x14";s/./chr(ord$&^30)/ge;print'