全局文件句柄

时间:2013-03-28 12:55:50

标签: perl file

我需要在几个perl模块中使用相同的文件句柄。这是我的例子 a.pl

#!/usr/bin/perl -w

our $OUT_FILE_HANDLE;

require b;

open($OUT_FILE_HANDLE, ">./a.log");
print $OUT_FILE_HANDLE "text1\n";

b::f($OUT_FILE_HANDLE); // this works

b.pm

package b;

sub f($) {
  my $a = shift;
  print $a "text2\n";  // get error here
}

f($main::OUT_FILE_HANDLE);
1;

我收到错误“无法使用未定义的值作为符号引用”

如果我直接在b.pm中使用句柄(不将其作为参数传递给函数),它可以正常工作

b.pm

package b;

sub f() {
  print $main::OUT_FILE_HANDLE "text2\n";  // this works
}

f();
1;

4 个答案:

答案 0 :(得分:9)

由于执行顺序,您的示例失败:all of b.pm is executed when you require b;。因此,您尝试在打开文件句柄之前使用它。

作为一般原则,模块应该只通过可以调用的函数来完成。只有在需要模块时才能运行初始化事项。

在这种情况下,最好的设计是使用 lexical 文件句柄并将其传递给任何需要它的函数。不要使用全局。

open(my $OUT_FILE_HANDLE, '>', './a.log') or die "Ouch: $!";
print $OUT_FILE_HANDLE "text1\n";

b::f($OUT_FILE_HANDLE);

使用全局变量与模块进行通信很少是一个好主意。偶尔,模块将全局暴露给调用代码可能是有用的,但反过来从来都不是一个好的设计。模块不应依赖于特定包中存在的特定变量才能工作。

最后,你几乎不应该在Perl中使用子程序原型。只要省略原型,除非你完全了解Perl原型并且有充分的理由使用它们:

sub f {

答案 1 :(得分:3)

您的代码存在许多问题。

  • 始终 use strictuse warnings位于您的计划顶部或package声明之后

  • CamelCase用于包名称,将snake_case用于本地标识符。熟悉Perl的人会感谢你

  • 对所有标识符使用描述性内容。特别是有一个名为B的核心包(Perl编译器后端),所以这不会做

  • 从不期望子模块访问main包中的数据。流程应严格自下而上

  • 从不使用原型进行子程序。 Perl在这方面与其他语言不同,原型做了一些非常特殊的事情。如果您不知道那些东西是什么,那么您当然不应该使用原型

  • 除非您知道它的作用,否则请勿使用require。你几乎肯定想要use

  • 使用open的三参数形式,始终检查是否成功。如果open失败,那么您应该die使用包含$!的字符串来说明为什么失败

您的代码无法按预期工作的主要原因是require(和use)语句将在包含它们时在辅助模块中执行任何可执行语句< / em>的。通常,此类模块将仅包含 definitions 声明以用于调用代码,如果包含任何可执行代码,则必须非常小心,因为正如您所见,它可能导致依赖项不可用的问题。

以下是您的代码的工作版本

<强> main.pl

use strict;
use warnings;

use BB;

open my $fh, '>', 'a.log' or die $!;
print $fh "text1\n";

BB::f($fh);

<强> BB.pm

package BB;

use strict;
use warnings;

sub f {
  my ($a) = @_;
  print $a "text2\n";
}

1;

输出(至a.log

text1
text2

答案 2 :(得分:1)

B是模块的错误名称,因为它是Perl core module。用BB重命名(例如)。另外,Perl注释使用'#',也不使用'//'。这是我修改过的代码(工作正常):

<强> main.pl

use BB;

our $OUT_FILE_HANDLE;
open($OUT_FILE_HANDLE, ">", "./a.log") or die $!;
print $OUT_FILE_HANDLE "text1\n";
BB::f($OUT_FILE_HANDLE);

<强> BB.pm

package BB;

sub f {
  my $a = shift;
  print $a "text2\n";  
}
1;

答案 3 :(得分:-1)

也许移动“我们的$ OUT_FILE_HANDLE;”在你的b.pm包中。