【问题标题】:Can you force flush output in Perl?你可以在 Perl 中强制刷新输出吗?
【发布时间】:2016-02-22 02:39:20
【问题描述】:

我在 Perl 中有以下两行:

print "Warning: this will overwrite existing files.  Continue? [y/N]: \n";
my $input = <STDIN>;

问题是在 Perl 脚本暂停输入之前打印行没有被执行。也就是说,Perl 脚本似乎无缘无故地无限期停止。我猜输出以某种方式缓冲(这就是我放入 \n 的原因,但这似乎没有帮助)。

【问题讨论】:

    标签: perl flush autoflush


    【解决方案1】:

    默认情况下,STDOUT 在连接到终端时是行缓冲的(由 LF 刷新),而在连接到终端以外的东西时是块缓冲的(当缓冲区满时刷新)。此外,&lt;STDIN&gt; 在连接到终端时会刷新 STDOUT。

    这意味着

    • STDOUT 未连接到终端,
    • 您没有打印到 STDOUT,或者
    • STDOUT 被搞砸了。

    print 在未提供句柄时打印到当前的selected 句柄,因此无论上述哪一个为真,以下操作都有效:

    # Execute after the print.
    # Flush the currently selected handle.
    # Needs "use IO::Handle;" in older versions of Perl.
    select()->flush();
    

    # Execute anytime before the <STDIN>.
    # Causes the currently selected handle to be flushed immediately and after every print.
    $| = 1;
    

    【讨论】:

    • 这是一个很好的答案,注意你也可以为特定句柄设置自动刷新STDERR-&gt;autoflush(1);
    • 确实如此,但请注意 STDERR 默认是自动刷新的。
    • @ikegami - 根据我的经验,STDERR并非总是自动刷新默认情况下
    • @ikegami - 这是一个简单的例子:perl -E 'use open ":std", ":encoding(UTF-8)"; print STDERR "foo"; sleep(5); say STDERR "bar"'perl -E 'use open ":std", ":encoding(UTF-8)"; STDERR-&gt;autoflush(1); print STDERR "foo"; sleep(5); say STDERR "bar"' 使用 CentOS Linux 版本 7.5.1804 (Core)Perl 5,版本 16 , 为 x86_64-linux-thread-multi 构建的 subversion 3 (v5.16.3)
    • @Ωmega,是的,虽然底层句柄是自动刷新的,但编码层添加了另一个缓冲区,但不是。这应该被报告为错误,恕我直言
    【解决方案2】:

    对于那些不想像保姆一样在每个print 之后调用flush() 的人,因为它可能在loop 或其他东西中,而您只是希望您的print 没有缓冲,然后简单地把它放在你的 perl 脚本的顶部:

    STDOUT->autoflush(1);
    

    此后,无需在print 之后调用flush()

    【讨论】:

      【解决方案3】:

      是的。我在我的 util.pl 文件中为此创建了一个子例程,在我所有的 Perl 程序中都是 required。

      ###########################################################################
      # In: File handle to flush.
      # Out: blank if no error,, otherwise an error message. No error messages at this time.
      # Usage: flushfile($ERRFILE);
      # Write any file contents to disk without closing file. Use at debugger prompt
      # or in program.
      sub flushfile
      {my($OUTFILE)=@_;
      my $s='';
      
      my $procname=(caller(0))[3]; # Get this subroutine's name.
      
      my $old_fh = select($OUTFILE);
      $| = 1;
      select($old_fh);
      
      return $s; # flushfile()
      }
      
      

      【讨论】:

        【解决方案4】:
        use IO::Handle;
        STDOUT->flush();
        

        【讨论】:

        • 对我来说,第一行 (use IO::Handle;) 不是必需的
        【解决方案5】:

        有几种方法可以打开自动刷新:

        $|++;
        

        在开头,或者还带有BEGIN 块:

        BEGIN{ $| = 1; }
        

        但是,您的配置似乎有些不寻常,因为通常末尾的 \n 会触发刷新(至少是终端)。

        【讨论】:

          猜你喜欢
          • 2012-02-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-07
          • 2017-01-01
          • 2012-11-08
          • 2010-11-16
          • 2020-01-04
          相关资源
          最近更新 更多