Reputation: 17
I like to have my scripts print out progress reports as the execute, so that I can tell whether they're working and how much longer I have to wait. But perl seems to print all output at the end, rather than as the commands are being executed. For example, this program waits for 10 seconds, then prints "before pauseafterpause" in at the same time:
print("before pause");
sleep 10;
print("after pause");
I have also tried with the same result:
my $filename="out";
open(OUT, ">>$filename");
print OUT "before pause";
sleep 10;
print OUT "after pause";
This happens whether I'm running locally or submitting to a cluster.
I know that this is possible by running perl scripts other people have written; but by looking at their code, I can't tell how they're doing it. Could anyone enlighten me? Thank you!
Upvotes: 1
Views: 1826
Reputation: 57630
Perl buffers your output for efficiency. If you print
to a terminal, then the output is line-buffered. End your info with a newline to have it display immediately:
print "before\n";
sleep 3;
print "after\n";
If your output is redirected (to a file or a pipe), then block-buffering is used because this is more efficient. This is usually OK (unless you are tail
ing the file). If not, you can turn off the buffering, by setting the $|
variable to 1
while the handle you want to unbuffer handle is currently selected (STDOUT by default):
local $| = 1;
print "before";
sleep 3;
print "after";
But genenerally, you should use the IO::Handle method for this:
$some_handle->autoflush(1);
...;
(see ikegami’s answer).
The STDERR
output handle is meant to be used for errors or any other output that is not the primary output of your program. It is unbuffered by default, and is very well suited to print progress reports. This works as well:
print STDERR "before";
sleep 3;
print STDERR "after";
Upvotes: 5
Reputation: 385877
First, stop using global variables for no reason. And add at least a simple check as to whether open
succeeded or not.
open(my $OUT, ">>", $filename) or die $!;
You simply have to turn off buffering
use IO::Handle; # Only needed for older versions of Perl
$OUT->autoflush(1);
Then you can print as normal.
print $OUT "text\n";
Upvotes: 3