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操作