我需要在几个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;
答案 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 strict
和use 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包中。