標籤:匯入 ast 執行順序 stderr init 訊號 tde 出現 ict
這是5個特殊的代碼塊。要理解這幾個塊,關鍵在於幾個時間點:
- (1).程式編譯期間
- (2).程式執行期間
- (3).程式執行結束但還未退出期間
BEGIN塊
- BEGIN塊是在程式編譯期間執行的,也就是上面的步驟(1)所在期間
- 即使程式中出現了語法錯誤,BEGIN塊也會執行
- 如果出現了多個BEGIN塊,則按照FIFO(first in first out)的方式輸出,也就是從上到下的順序
在BEGIN期間可以做一些程式執行之前的操作,例如事先給某個比較特殊的變數賦值,檢查檔案是否存在,檢查作業系統是否滿足要求等等。
package Foo;use strict;use warnings;BEGIN { print "This is the first BEGIN block\n";}print "The program is running\n";BEGIN { print "This is the second BEGIN block\n";}
由於BEGIN代碼塊在編譯期間執行,程式普通行的print是在執行期間執行,所以上面的代碼結果為:
This is the first BEGIN blockThis is the second BEGIN blockThe program is running
下面程式出現語法錯誤,但BEGIN也會執行:
BEGIN { print "This is the first BEGIN block\n";}print "The program is running\n";BEGIN { print "This is the second BEGIN block\n";}my $x =;
執行結果:
syntax error at some_program.pl line 8, near "=;"Execution of some_program.pl aborted due to compilation errors.This is the first BEGIN blockThis is the second BEGIN block
不過上面的error資訊不一定會最先輸出,因為stdout和stderr是兩個獨立的檔案控制代碼,無法保證它們之間的順序。
實際上,use匯入模組時如果匯入的是空列表,它等價於在BEGIN中使用require語句:
use File::Find ();# 等價於BEGIN { require File::Find;}
END塊
END塊是在程式執行結束,但退出前執行的,也就是上面的步驟(3)所在期間。
- 當觸發了die的時候,它們也會執行
- 但可以通過訊號來忽略END
- 它們的執行順序是LIFO(last in first out),即從下往上輸出
- END常用來做清理、善後操作
END { print "This is the first END block\n";}END { print "This is the second END block\n";}
輸出結果:注意,先輸出second END,再輸出first END
This is the second END blockThis is the first END block
INIT、CHECK 和 UNITCHECK 塊
INIT、CHECK 和 UNITCHECK 塊生效於程式編譯結束之後、執行之前。所以如果語法錯誤,它們不會被觸發。
- CHECK在編譯結束後立即執行,即上面步驟(1)剛完成之後,輸出格式為LIFO
- INIT緊跟在CHECK之後,也是在步驟(2)之前,輸出格式為FIFO
- UNITCHECK是在perl 5.9.5之後引入的功能。用於解決執行期間require或do或eval匯入檔案時不觸發CHECK和INIT的問題(因為這些語句的匯入是在執行期間進行的,而這兩個塊是在編譯期間進行的)。UNITCHECK是在匯入的檔案剛編譯完成之後、執行之前立即執行的
INIT { print "This is the first INIT block\n";}CHECK { print "This is the first CHECK block\n";}INIT { print "This is the second INIT block\n";}CHECK { print "This is the second CHECK block\n";}
輸出結果:
This is the second CHECK blockThis is the first CHECK blockThis is the first INIT blockThis is the second INIT block
Perl的特殊代碼塊:BEGIN、CHECK、INIT、END和UNITCHECK