views:

142

answers:

5

I have a computationally expensive task in perl, and would like to inform the user that computation is ongoing by printing out a period after each portion of the computation is completed. Unfortunately, until I print a "\n", none of my periods are printed. How can I address this?

+4  A: 

set $|=1 before you start printing. Eg.

perl -e ' $|=1; foreach (1..10) { print "$_ "; sleep(1); }'
Martin
+1, because someone marked a working solution down.
ar
@ar, `STDOUT->autoflush(1)` is the same thing as `$|=1` except `$|=1`, is global and `STDOUT->autoflush(1)` is specific to one handle.
Evan Carroll
Except you have to do a `use IO::Handle`. Not that `IO::Handle` hasn't been a standard module for eons, but ... yeah. :(`
Robert P
+10  A: 

You need to set autoflush for STDOUT. Example:

use IO::Handle;
STDOUT->autoflush(1);
foreach (1..20) {
  print '.';
  sleep(1);
}
Alexandr Ciornii
@Hans Please do not link to unauthorized copies of books.
Sinan Ünür
See http://oreilly.com/catalog/9780596003135 and http://oreilly.com/catalog/9780596003135 .
Sinan Ünür
Sorry, it just popped up when I searched the web. Now removed the link.
Hans W
+2  A: 

See the FAQ How do I flush/unbuffer an output filehandle? Why must I do this? and note:

Besides the $| special variable, you can use binmode to give your filehandle a :unix layer, which is unbuffered ...

For the general problem, you might want to look at Time::Progress:

%b

%B

progress bar which looks like:

##############......................
Sinan Ünür
+4  A: 

An excellent article you should read: Suffering from Buffering?

ysth
A: 

What worked for me was to put the line

STDOUT->autoflush(1);

before my line

print ".";

inside my existing loop. Didn't use the sleep for fear of slowing the things down even more.

ekemmler