【问题标题】:Why is three-argument open calls with autovivified filehandles a Perl best practice?为什么使用自动激活文件句柄的三参数开放调用是 Perl 的最佳实践?
【发布时间】:2010-12-01 13:44:47
【问题描述】:

我有两个关于 Perl open 函数的问题:

1) 我似乎从 Perl Best Practices 中记得 open 的 3 参数版本比两个参数版本更好,例如

open(OUT, '>>', $file);

对比

open(OUT, ">>$file");

这是为什么呢?前几天我试图告诉某人使用 3 参数版本,但似乎无法用任何东西来支持它。

2) 我似乎还记得 autovivified 文件句柄比裸字文件句柄更受青睐(它们叫不同的东西)?而且也不记得为什么,例如

open(my $out, '>>', $file);

对比

open(OUT, '>>', $file);

这是strict 的事情吗?我似乎记得可以将OUTstrict 一起使用,但我不记得了。

【问题讨论】:

  • 这是因为 Perl::Critic 建议这样做 :)
  • 不是骗子,这是在问为什么这是最好的方法。
  • 抱歉编辑...我从来没有听说过这些被称为“自动激活文件句柄”(我一直听说过“词法文件句柄”)并试图提高可搜索性,但现在我真的看到了自动激活参与其中,文档确实以这种方式引用它们。回滚到以前的版本。

标签: perl file-io scope


【解决方案1】:
  • 对文件句柄(如 OUT)使用 typeglob 不是一个好主意,因为它们在整个程序中都是全局的 - 您需要确保没有其他例程(包括模块中的例程)使用相同的名称(包括在未来)。
  • 使用双参数形式的 open 会使您的应用程序暴露于由包含特殊字符的变量引起的错误行为,例如 my $f; open $f, ">$some_filename"; 会暴露在 $some_filename 包含前导 > 会改变程序行为的错误中.

使用三参数形式通过将模式和文件名分隔为它们不能干扰的单独参数来避免这种情况。

此外,使用管道的大量参数形式是一个非常好的主意:

open $pipe, '|-', 'sendmail', 'fred@somewhere.fake';

比将所有这些都作为单个字符串执行要好——它避免了可能的 shell 注入等。

【讨论】:

  • 感谢 MarkR。这几乎正​​是我正在寻找的一组答案。很高兴知道在过去的几年里我这样做是有正当理由的。
  • 兼容性注意事项:3-arg open 和 open my $fh, ... 从 5.6.0 开始工作。 open my $fh, '|-', LIST(列表管道打开)从 5.8.0 开始工作。
  • 没有理由对已知内容的文字使用丑陋的管道打开形式,例如建议的内容。此外,您打破了复杂管道的外壳处理。坏坏坏。
  • 我还想指出,autovivified 文件句柄 更容易作为参数传递给方法和子例程。您甚至可以在子例程中打开文件,并将文件句柄传回给调用者。
【解决方案2】:

解决 #2:

OUT 是一个全局文件句柄,使用它会使您面临如下隐蔽的错误:

sub doSomething {
  my ($input) = @_;
  # let's compare $input to something we read from another file
  open(F, "<", $anotherFile);
  @F = <F>; 
  close F;
  &do_some_comparison($input, @F);
}

open(F, "<", $myfile);
while (<F>) {
    &doSomething($_);   # do'h -- just closed the F filehandle
}
close F;

【讨论】:

  • 啊,这是一个非常可靠的推理。
【解决方案3】:

要记住的一个方面是双参数形式被破坏了。考虑一个名为“abc”的文件(即带有前导空格的文件名)。您无法打开该文件:

open my $foo, ' abc' or die $!;
open my $foo, '< abc' or die $!;
open my $foo, '<  abc' or die $!;
# nothing works

空间被删除,因此无法再找到该文件。这种情况极不可能发生,但绝对是个问题。三参数形式对此免疫:

open my $foo, '<', ' abc' or die $!;
# works

This thread 来自 perlmonks 的讨论与任何问题一样好。请记住,在 2001 年,三参数形式仍然被认为是 new,因此不适合可移植代码,因为如果在 5.005 解释器上运行 Perl 程序会因语法错误而死掉。现在不再是这种情况了:perl 5.005 已经过时了,已经过时了。

【讨论】:

  • 不,open 的双参数形式或单参数形式没有被破坏。它按设计、记录和宣传的方式工作。可能只是 magic open 不是您所需要的。三参数开放的另一个插件是中间参数可以——而且通常应该——包括流的编码。
猜你喜欢
  • 1970-01-01
  • 2012-07-15
  • 2017-04-28
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多