我喜欢让我的脚本打印出进度报告作为执行,以便我可以判断它们是否正在工作以及我需要等待多长时间。但是perl似乎在最后打印所有输出,而不是在执行命令时打印。例如,该程序等待10秒钟,然后同时打印“暂停后暂停”:
print("before pause");
sleep 10;
print("after pause");
我也尝试过相同的结果:
my $filename="out";
open(OUT, ">>$filename");
print OUT "before pause";
sleep 10;
print OUT "after pause";
无论我是在本地运行还是提交到群集,都会发生这种情况。
我知道通过运行其他人编写的perl脚本可以实现这一点;但通过查看他们的代码,我无法分辨他们是如何做到的。谁能开导我?谢谢!
答案 0 :(得分:5)
Perl缓冲输出以提高效率。如果您print
到终端,则输出是行缓冲的。使用换行符结束您的信息,以便立即显示:
print "before\n";
sleep 3;
print "after\n";
如果您的输出被重定向(到文件或管道),则使用块缓冲,因为这更有效。这通常没问题(除非你是tail
文件)。如果没有,您可以通过将$|
变量设置为1
来关闭缓冲,同时当前选择要解除缓冲处理的句柄(默认为STDOUT):
local $| = 1;
print "before";
sleep 3;
print "after";
但通常情况下,您应该使用IO :: Handle方法:
$some_handle->autoflush(1);
...;
(见ikegami的回答)。
STDERR
输出句柄用于错误或任何其他不是程序主要输出的输出。默认情况下它是无缓冲的,非常适合打印进度报告。这也有效:
print STDERR "before";
sleep 3;
print STDERR "after";
答案 1 :(得分:3)
首先,无缘无故地停止使用全局变量。并至少添加一个关于open
是否成功的简单检查。
open(my $OUT, ">>", $filename) or die $!;
您只需关闭缓冲
use IO::Handle; # Only needed for older versions of Perl
$OUT->autoflush(1);
然后你可以照常打印。
print $OUT "text\n";