読者です 読者をやめる 読者になる 読者になる

Perlでバッファリング抑止

Perl

前回の続きです。
Perlの出力バッファリングを抑止したいときはオートフラッシュを有効化します。
そうするとprint、printf、writeを実行するごとにバッファがフラッシュされる、つまりprint、即出力が実現できます。


じゃやってみます。

標準出力のオートフラッシュ

$|変数に1を代入します。元に戻すのは$|=0です。
(use English;$OUTPUT_AUTOFLUSH=1;としてもいいですが、まぁやる人いませんよね)

#! /usr/bin/perl

$|=1;
for(1..5){
  print;
  sleep 1;
}
$|=0

ファイルハンドル他のオートフラッシュ

$|によるオートフラッシュの設定は、現在selectされている出力ハンドルに対して働きます。
なので設定したい出力ハンドルをselectしてから$|=1をしてやればOKです。
(selectの返り値使ってちゃんと後始末もしときましょう。)

#! /usr/bin/perl

open my $fh, ">>", "test.log";

my $old = select $fh;
$|=1;
select $old;

for(1..5){
  print $fh $_;
  sleep 1;
}

close $fh;


この部分、なんかめんどくさい、テンポラリ変数作りたくない、

my $old = select $fh;
$|=1;
select $old;

という場合はこんな書き方もできます。

select((select($fh), $|=1)[0]);


可読性を重視するならIO::Handleのautoflushを使いましょう。

#! /usr/bin/perl
use IO::Handle;

open my $fh, ">>", "test.log";

$fh->autoflush;

for(1..5){
  print $fh $_;
  sleep 1;
}

close $fh;

IO::Handleは小さなモジュールではないですがselectと$|を使う方法と比べて格段に読みやすいと思います。
もちろん標準出力の場合も$|を使わずSTDOUT->autoflush;と書くこともできます。


$fh->autoflush;は以下のようにも書き換えられます。

autoflush $fh 1;
autoflush $fh;
$fh->autoflush(1);