Perl5 的程序执行分为两个阶段:compilation time & run time。而 use 与 require 依次发生在这两个不同的阶段。
值得注意的是:Parser对use的处理等同如下:
use strict;
like
BEGIN{
require 'strict.pm';
strict->import();
}
NOTE:BEGIN block是在compilation time触发执行(赋值)过程。
也就是说,strict 中所定义的variables & subroutines已于compilation time在data structure(optree)中赋值并存在了。
接下来通过对不同路径下,拥有相同包package name or file name的文件导入来分析它们的不同表现。
use PACKAGE;
/tmp/amy_dir/hello.pm
sub say(){
print "Hello! I am Amy\";
}
1;
__END__;
/tmp/bob_dir/hello.pm
sub say(){
print "Hello! I am Bob\";
}
1;
__END__;
/tmp/say_hello.pl
use lib "/tmp/amy_dir";
use hello;
hello->say();
use lib "/tmp/bob_dir";
use hello;
hello->say();
运行结果:
[root@VTB93-PC1 tmp]# perl say_hello.pl
Hello! I am Amy
Hello! I am Amy
分析:上面提到 use 等同 BEGIN{…}。amy_dir目录下的 hello.pm 先被赋值于optree中, 后续Parser再遇上 bob_dir下的hello.pm时,发现optree中已存在以此包名为值的 key,将不再进行二次赋值。所以在 run time 顺序执行代码时,所有对 hello->say() 的调用都是参照/tmp/amy_dir/hello.pm
require “some_file.pl(pm)”;
Perl5对 require 的处理是在 run time。当执行require时会在run time触发编译。
接下来将/tmp/say_hello.pl中的 use 部分替换成 require 后:
[root@VTB93-PC1 tmp]# vi say_hello.pl
use lib "/tmp/amy_dir";
require 'hello.pm';
hello->say();
use lib "/tmp/bob_dir";
require 'hello.pm';
hello->say();
运行结果:
[root@VTB93-PC1 tmp]# perl say_hello.pl
Hello! I am Bob
Hello! I am Bob
分析:在run time 执行到 require 语句触发编译。这边可以理解为 say_hello.pl 中最终包含了 /tmp/bob_dir/hello.pm 中的代码。这是由于 @INC 中的优先路径为 /tmp/bob_dir/。导致 @INC 如此的是由于编译时,两次 use lib 操作的顺序所致。
[root@VTB93-PC1 tmp]# perl say_hello.pl
Hello! I am Bob
Dump @INC
(
"/tmp/bob_dir",
"/tmp/amy_dir",
"/usr/local/lib/perl5",
"/usr/local/share/perl5",
"/usr/lib/perl5/vendor_perl",
"/usr/share/perl5/vendor_perl",
"/usr/lib/perl5",
"/usr/share/perl5",
".",
)
Hello! I am Bob
Dump @INC
(
"/tmp/bob_dir",
"/tmp/amy_dir",
"/usr/local/lib/perl5",
"/usr/local/share/perl5",
"/usr/lib/perl5/vendor_perl",
"/usr/share/perl5/vendor_perl",
"/usr/lib/perl5",
"/usr/share/perl5",
".",
)
结论:
- 先后 use 不同路径下,拥有相同package name的 pm,只会导入第一个pm
- 先后 require 不同路径下,拥有相同name的pl or pm file, 只会导入后一个file
- use lib LIST, 对@INC进行unshift操作