你什么时候需要在Perl中"结束{关闭STDOUT}"?

jm6*_*666 15 perl

tchrists broilerplate中,我发现在END块中明确关闭了STDOUT.

END { close STDOUT }
Run Code Online (Sandbox Code Playgroud)

我知道结束并关闭,但我想知道为什么需要它.

当开始搜索它时,在perlfaq8中找到以下内容:

例如,您可以使用它来确保您的过滤器程序设法完成其输出而不填满磁盘:

END {
    close(STDOUT) || die "stdout close failed: $!";
}
Run Code Online (Sandbox Code Playgroud)

并且无论如何也不理解.:(

有人可以解释(可能有一些代码示例):

  • 为何以及何时需要它
  • 我的perl过滤器如何以及在什么情况下可以填满磁盘等等.
  • 没有它时出现问题...
  • 等等??

Mat*_*Mat 15

许多系统实现"乐观"文件操作.我的意思是,print在数据实际写入文件之前,或者甚至在磁盘上保留足够的空间以使写入成功之前,对文件添加一些数据的调用可以成功返回.

在这些情况下,如果磁盘几乎已满,则所有打印都可以显示成功,但是当需要关闭文件并将其刷新到磁盘时,系统会意识到没有剩余空间.然后关闭文件时出错.

此错误意味着您认为保存的所有输出实际上可能根本没有保存(或部分保存).如果这很重要,您的程序需要报告错误(或尝试纠正这种情况,或者......).

所有这些都可以在STDOUT文件句柄上发生,如果它连接到文件,例如,如果您的脚本运行如下:

perl script.pl > output.txt
Run Code Online (Sandbox Code Playgroud)

如果您输出的数据很重要,并且您需要知道所有数据是否确实写得正确,那么您可以使用您引用的语句来检测问题.例如,在第二个代码段中,die如果close报告错误,脚本会显式调用; tchrist的样板运行在use autodie,die如果close失败则会自动调用.

(这不能保证数据永久存储在磁盘上,其他因素也会在那里发挥作用,但这是一个很好的错误指示.即如果关闭失败,你知道你有问题.)

  • @ jm666:tchrist的样板文件的一部分(来自哪里)是`use autodie;`来处理错误 (3认同)
  • 每个脚本都不需要**.许多脚本只是将随机信息消息写入stdout,并不关心它是否连接到任何东西.它只需要**如果**写入该文件描述符的数据是**重要的**,当然并非总是如此. (3认同)
  • 我保护`END {close STDOUT}`的唯一一次是当它进入管道时.即便如此,有时候我会有一个`$ SIG {PIPE} = sub {exit 0}`而不是一般来说,过滤程序没有检测到STDOUT失败的错误.我偶尔会延迟安装atexit处理程序,如`eval qq {END {close STDOUT}}`或者使用`END {eval {close STDOUT}}`保护它不受`autodie`的影响.但是当你有STDOUT进入管道时,按照'开放(STDOUT,"|少")`,你当然最好等待它,否则你的父母会在孩子面前退出,搞砸输出.**默认情况下,假设您需要它.** (3认同)
  • @ jm666,我刚刚尝试用perl写入一个完整的磁盘.Bash在关闭文件时不会**给出错误,并且它返回零错误代码(成功),而对文件的写入尚未完成!所以shell不是我在这里所依赖的.添加`END`子句使perl本身barf成为正确的警告,并通过`die`ing宣告失败. (2认同)
  • @ jm666:'close STDOUT`的关键不是关闭流,当perl进程退出时,无论如何都会发生这种情况.关键是**如果'close`失败,那么进程将以非零状态代码退出,表示失败**.这是由`使用autodie`或由'close STDOUT ||'完成的 在你的另一个例子中死掉. (2认同)