14

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?

brian d foy
  • 129,424
  • 31
  • 207
  • 592
shino
  • 4,562
  • 5
  • 38
  • 57

5 Answers5

17

You need to set autoflush for STDOUT. Example:

use IO::Handle;
STDOUT->autoflush(1);
foreach (1..20) {
  print '.';
  sleep(1);
}
Alexandr Ciornii
  • 7,346
  • 1
  • 25
  • 29
7

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

perl -e ' $|=1; foreach (1..10) { print "$_ "; sleep(1); }'
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
Martin
  • 9,674
  • 5
  • 36
  • 36
  • @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 Mar 12 '10 at 17:18
  • 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 Mar 12 '10 at 17:37
4

An excellent article you should read: Suffering from Buffering?

ysth
  • 96,171
  • 6
  • 121
  • 214
2

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:

##############......................
Community
  • 1
  • 1
Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
0

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.

John Conde
  • 217,595
  • 99
  • 455
  • 496