Perl 中 BEGIN 块的作用是什么? [英] What is the role of the BEGIN block in Perl?
问题描述
我知道 BEGIN 块是在 Perl 程序主体之前编译和执行的.如果您不确定,请尝试通过此命令运行 perl -cw 命令:
I know that the BEGIN block is compiled and executed before the main body of a Perl program. If you're not sure of that just try running the command perl -cw over this:
#!/ms/dist/perl5/bin/perl5.8
use strict;
use warnings;
BEGIN {
print "Hello from the BEGIN block\n";
}
END {
print "Hello from the END block\n";
}
有人告诉我,早期编译和执行 BEGIN 块可以让程序员确保在执行主程序之前可以使用任何所需的资源.
I have been taught that early compilation and execution of a BEGIN block lets a programmer ensure that any needed resources are available before the main program is executed.
所以我一直在使用 BEGIN 块来确保诸如数据库连接之类的东西已经建立并且可供主程序使用.同样,我使用 END 块来确保在程序终止之前关闭、删除、终止所有资源.
And so I have been using BEGIN blocks to make sure that things like DB connections have been established and are available for use by the main program. Similarly, I use END blocks to ensure that all resources are closed, deleted, terminated, etc. before the program terminates.
在今天早上的讨论之后,我想知道这是否是查看 BEGIN 和 END 块的错误方式.
After a discussion this morning, I am wondering if this the wrong way to look at BEGIN and END blocks.
在 Perl 中 BEGIN 块的预期作用是什么?
What is the intended role of a BEGIN block in Perl?
更新 1: 刚刚发现 DBI 连接不起作用的原因.在得到这个小小的 Perl 程序之后:
Update 1: Just found out why the DBI connect didn't work. After being given this little Perl program:
use strict;
use warnings;
my $x = 12;
BEGIN {
$x = 14;
}
print "$x\n";
执行时打印 12.
更新 2:感谢 Eric Strom 在这个新版本下面的评论,使之更清晰:
Update 2: Thanks to Eric Strom's comment below this new version makes it clearer:
use strict;
use warnings;
my $x = 12;
my $y;
BEGIN {
$x = 14;
print "x => $x\n";
$y = 16;
print "y => $y\n";
}
print "x => $x\n";
print "y => $y\n";
输出是
x => 14
y => 16
x => 12
y => 16
再次感谢 Eric!
推荐答案
您是否尝试过将 BEGIN{}
块替换为 INIT{}
块?这是 modperl 等使用一次编译,多次运行"模型的标准方法,因为您需要在每次单独运行时重新初始化,而不仅仅是在编译期间初始化一次.
Have you tried swapping out the BEGIN{}
block for an INIT{}
block? That's the standard approach for things like modperl which use the "compile-once, run-many" model, as you need to initialize things anew on each separate run, not just once during the compile.
但我不得不问为什么它无论如何都在特殊块中.你为什么不做某种prepare_db_connection()
函数,然后在程序启动时根据需要调用它?
But I have to ask why it's all in special block anyway. Why don't you just make some sort of prepare_db_connection()
function, and then call it as you need to when the program starts up?
在 BEGIN{}
中不起作用的东西,如果它是模块文件中的主线代码,它会被 use
d 使用,也会有同样的问题.这是使用 INIT{}
块的另一个可能原因.
Something that won't work in a BEGIN{}
will also have the same problem if it's main-line code in a module file that gets use
d. That's another possible reason to use an INIT{}
block.
我还看到了相互递归的致命拥抱问题,必须使用诸如 require
而不是 use
或 INIT{ 之类的东西来解决这些问题}
而不是 BEGIN{}
.但这种情况很少见.
I've also seen deadly-embrace problems of mutual recursion that have to be unravelled using something like an require
instead of use
, or an INIT{}
instead of a BEGIN{}
. But that's pretty rare.
考虑这个程序:
% cat sto-INIT-eg
#!/usr/bin/perl -l
print " PRINT: main running";
die " DIE: main dying\n";
die "DIE XXX /* NOTREACHED */";
END { print "1st END: done running" }
CHECK { print "1st CHECK: done compiling" }
INIT { print "1st INIT: started running" }
END { print "2nd END: done running" }
BEGIN { print "1st BEGIN: still compiling" }
INIT { print "2nd INIT: started running" }
BEGIN { print "2nd BEGIN: still compiling" }
CHECK { print "2nd CHECK: done compiling" }
END { print "3rd END: done running" }
仅当编译时,它会产生:
When compiled only, it produces:
% perl -c sto-INIT-eg
1st BEGIN: still compiling
2nd BEGIN: still compiling
2nd CHECK: done compiling
1st CHECK: done compiling
sto-INIT-eg syntax OK
当编译和执行时,它会产生:
While when compiled and executed, it produces this:
% perl sto-INIT-eg
1st BEGIN: still compiling
2nd BEGIN: still compiling
2nd CHECK: done compiling
1st CHECK: done compiling
1st INIT: started running
2nd INIT: started running
PRINT: main running
DIE: main dying
3rd END: done running
2nd END: done running
1st END: done running
并且 shell 根据 die
报告退出 255.
And the shell reports an exit of 255, per the die
.
您应该能够安排在需要时进行连接,即使 BEGIN{}
证明为时过早.
You should be able to arrange to have the connection happen when you need it to, even if a BEGIN{}
proves too early.
嗯,刚想起来.您不可能在 BEGIN{}
中使用 DATA
做某事,是吗?直到解释器运行时才设置;它不对编译器开放.
Hm, just remembered. There's no chance you're doing something with DATA
in a BEGIN{}
, is there? That's not set up till the interpreter runs; it's not open to the compiler.
这篇关于Perl 中 BEGIN 块的作用是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!