Perl 中 BEGIN 块的作用是什么? [英] What is the role of the BEGIN block in Perl?

查看:47
本文介绍了Perl 中 BEGIN 块的作用是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道 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{} 中不起作用的东西,如果它是模块文件中的主线代码,它会被 used 使用,也会有同样的问题.这是使用 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 used. That's another possible reason to use an INIT{} block.

我还看到了相互递归的致命拥抱问题,必须使用诸如 require 而不是 useINIT{ 之类的东西来解决这些问题} 而不是 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆