尝试打印到已关闭的文件句柄时没有错误或警告
No error or warning for trying to print to an already closed filehandle
在下面的小代码中,第 [09] 和 [18] 行没有出现错误或警告。我得到的唯一警告是行 [21]:
use strict; # [01]
use warnings FATAL => 'unopened'; # [02]
# [03]
open(my $outHandleA, ">outputA.txt") or die ("A: $!\n"); # [04] Opened $outHandleA
print $outHandleA "FILE A\n"; # [05]
close $outHandleA; # [06] Closed $outHandleA
# [07]
print $outHandleA; # [08]
print $outHandleA "ABC\n"; # [09] <---
print $outHandleA; # [10]
print "-----"; # [11]
# [12]
open(OUT, ">outputB.txt") or die ("B: $!\n"); # [13] Opened OUT
print OUT "FILE B\n"; # [14]
close OUT; # [15] Closed OUT
# [16]
print OUT; # [17]
print OUT "DEF\n"; # [18] <---
print OUT; # [19]
# [20]
print DOES_NOT_EXIST_HANDLE "GHI\n"; # [21] Raises a FATAL warning
# [22]
print "JKL"; # [23] Does not reach here (as expected)
但是,第 [09] 和 [18] 行不应该也引发如下错误或警告,因为它已关闭(未打开)吗?
- 错误:
print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
- 警告:
print() on unopened filehandle $outHandleA at printingToClosedHandle.pl line 9.
这可能是我的 Perl 版本的问题,它是“为 MSWin32-x64-多线程构建的 perl 5,版本 28,颠覆 1 (v5.28.1)”。此外,这是我在下面得到的程序的输出:
outputA.txt
outputB.txt
STDOUT
FILE A
FILE B
GLOB(0xfeb428)GLOB(0xfeb428)-----
上面 table 中的 STDOUT 输出来自第 [08]、[10] 和 [11] 行。请注意,上面 table 中括号 (...) 之间的值可能会随着每次执行而改变。
已经打开(初始化)并关闭的文件句柄与根本没有打开的文件句柄是有区别的;尝试向他们打印会引发不同的警告。 'unopened' entries in perldiag 之一说
%s() on unopened %s
(W unopened) An I/O operation was attempted on a filehandle that was never initialized. You need to do an open(), a sysopen(), or a socket() call, or call a constructor from the FileHandle package.
而 print() on closed filehandle 的条目说
print() on closed filehandle %s
(W closed) The filehandle you're printing on got itself closed sometime before now. Check your control flow.
虽然他们都收到了警告。
单独启用 use warnings FATAL => 'unopened'
时打印到已初始化但随后关闭的文件句柄不会收到警告。
use warnings;
#use warnings FATAL => 'unopened';
use strict;
use feature 'say';
open my $stdout, '>&', *STDOUT; # a copy
say $stdout "hi";
close $stdout;
say $stdout "to lexical, closed"; # it warns (l.10)
FATAL_warnings_unopened: {
no warnings; # change to FATAL for 'unopened'
use warnings FATAL => 'unopened';
say $stdout "with FATAL to closed fh"; # no warning
close STDOUT;
say "with FATAL to STDOUT"; # no warning
say NON_EXISTENT_FH "no such filehandle!"; # l.20
};
say STDERR 'done';
这会打印
hi
say() on closed filehandle $stdout at warnings_FATAL.pl line 10.
say() on unopened filehandle NON_EXISTENT_FH at warnings_FATAL.pl line 20.
根据 FATAL 和块内的 unopened
文件句柄 NON_EXISTENT_FH
,它确实退出了,但是没有关于在其正上方打印到 $stdout
的警告。第一个这样的打印有一个警告。刚刚关闭的 STDOUT
的打印也不会收到警告。
如果我们在最开始取消注释 use warnings FATAL...
行(并删除其他 warnings
行),则根本不会发出打印到关闭句柄的警告。
仔细阅读 warnings pragma 的文档很有帮助。简而言之,我建议始终先单独使用 use warnings;
,然后为要创建的类别添加一个语句 FATAL
(可以在同一语句中添加多个类别)。
您 运行 与 use
的细节及其背后的导入机制发生冲突。即,如果您 use Foo 'bar';
,那么 仅 Foo::bar
将被导入,即使 Foo
通常导出其他内容。
同理,use warnings FATAL => 'unopened';
不转所有警告。它只打开 'unopened' 警告:
$ perl -E 'use warnings FATAL => "unopened" ; print $x;'
$ perl -E 'use warnings; use warnings FATAL => "unopened" ; print $x;'
Name "main::x" used only once: possible typo at -e line 1.
Use of uninitialized value $x in print at -e line 1.
在下面的小代码中,第 [09] 和 [18] 行没有出现错误或警告。我得到的唯一警告是行 [21]:
use strict; # [01]
use warnings FATAL => 'unopened'; # [02]
# [03]
open(my $outHandleA, ">outputA.txt") or die ("A: $!\n"); # [04] Opened $outHandleA
print $outHandleA "FILE A\n"; # [05]
close $outHandleA; # [06] Closed $outHandleA
# [07]
print $outHandleA; # [08]
print $outHandleA "ABC\n"; # [09] <---
print $outHandleA; # [10]
print "-----"; # [11]
# [12]
open(OUT, ">outputB.txt") or die ("B: $!\n"); # [13] Opened OUT
print OUT "FILE B\n"; # [14]
close OUT; # [15] Closed OUT
# [16]
print OUT; # [17]
print OUT "DEF\n"; # [18] <---
print OUT; # [19]
# [20]
print DOES_NOT_EXIST_HANDLE "GHI\n"; # [21] Raises a FATAL warning
# [22]
print "JKL"; # [23] Does not reach here (as expected)
但是,第 [09] 和 [18] 行不应该也引发如下错误或警告,因为它已关闭(未打开)吗?
- 错误:
print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
- 警告:
print() on unopened filehandle $outHandleA at printingToClosedHandle.pl line 9.
这可能是我的 Perl 版本的问题,它是“为 MSWin32-x64-多线程构建的 perl 5,版本 28,颠覆 1 (v5.28.1)”。此外,这是我在下面得到的程序的输出:
outputA.txt | outputB.txt | STDOUT |
---|---|---|
FILE A | FILE B | GLOB(0xfeb428)GLOB(0xfeb428)----- |
上面 table 中的 STDOUT 输出来自第 [08]、[10] 和 [11] 行。请注意,上面 table 中括号 (...) 之间的值可能会随着每次执行而改变。
已经打开(初始化)并关闭的文件句柄与根本没有打开的文件句柄是有区别的;尝试向他们打印会引发不同的警告。 'unopened' entries in perldiag 之一说
%s() on unopened %s
(W unopened) An I/O operation was attempted on a filehandle that was never initialized. You need to do an open(), a sysopen(), or a socket() call, or call a constructor from the FileHandle package.
而 print() on closed filehandle 的条目说
print() on closed filehandle %s
(W closed) The filehandle you're printing on got itself closed sometime before now. Check your control flow.
虽然他们都收到了警告。
单独启用 use warnings FATAL => 'unopened'
时打印到已初始化但随后关闭的文件句柄不会收到警告。
use warnings;
#use warnings FATAL => 'unopened';
use strict;
use feature 'say';
open my $stdout, '>&', *STDOUT; # a copy
say $stdout "hi";
close $stdout;
say $stdout "to lexical, closed"; # it warns (l.10)
FATAL_warnings_unopened: {
no warnings; # change to FATAL for 'unopened'
use warnings FATAL => 'unopened';
say $stdout "with FATAL to closed fh"; # no warning
close STDOUT;
say "with FATAL to STDOUT"; # no warning
say NON_EXISTENT_FH "no such filehandle!"; # l.20
};
say STDERR 'done';
这会打印
hi say() on closed filehandle $stdout at warnings_FATAL.pl line 10. say() on unopened filehandle NON_EXISTENT_FH at warnings_FATAL.pl line 20.
根据 FATAL 和块内的 unopened
文件句柄 NON_EXISTENT_FH
,它确实退出了,但是没有关于在其正上方打印到 $stdout
的警告。第一个这样的打印有一个警告。刚刚关闭的 STDOUT
的打印也不会收到警告。
如果我们在最开始取消注释 use warnings FATAL...
行(并删除其他 warnings
行),则根本不会发出打印到关闭句柄的警告。
仔细阅读 warnings pragma 的文档很有帮助。简而言之,我建议始终先单独使用 use warnings;
,然后为要创建的类别添加一个语句 FATAL
(可以在同一语句中添加多个类别)。
您 运行 与 use
的细节及其背后的导入机制发生冲突。即,如果您 use Foo 'bar';
,那么 仅 Foo::bar
将被导入,即使 Foo
通常导出其他内容。
同理,use warnings FATAL => 'unopened';
不转所有警告。它只打开 'unopened' 警告:
$ perl -E 'use warnings FATAL => "unopened" ; print $x;'
$ perl -E 'use warnings; use warnings FATAL => "unopened" ; print $x;'
Name "main::x" used only once: possible typo at -e line 1.
Use of uninitialized value $x in print at -e line 1.