2009-06-25 129 views
6

可以分配給$!在Perl中的錯誤?

例如,

if(! (-e $inputfile)) 
{ 
     $! = "Input file $inputfile appears to be non-existent\n"; 
     return undef; 
} 

這樣我可以在頂級處理所有的錯誤。

謝謝。

+1

我不認爲Perl會被認爲是猶太教...;) – 2009-06-25 18:43:47

回答

12

如果分配到$ !,它被放置在系統errno變量,只需要數字。所以,你其實可以做的事:

use Errno "EEXIST"; 
$! = EEXIST; 
print $!; 

,並獲得一個定義的系統錯誤號的字符串值,但你想要的東西,你不能這樣做 - 將其設置爲任意字符串。這樣的字符串會給你一個參數「...」在標量賦值警告中不是數值,並將errno設置爲0.

另一個問題是$!可能會被任何系統調用改變。所以你只能相信它有你設置的價值,直到你做一個印刷或其他任何東西。你可能需要你自己的錯誤變量。

2

是的,你可以分配東西(#)到$!,只是要警惕你做的地方,所以你不要搞亂一些其他功能的消息。

9

那麼,documentation說,這基本上是一個系統錯誤的指標。所以我不會分配它,你只是讓你的lib的用戶發瘋。

使用異常,而不是:

eval { # this ain't the evil eval 
    # some code 
    die $something; 
} 
if (my $err = [email protected]) { 
    # exception handling 
} 

注意,您可以「拋」,或死亡,大約有您需要什麼..

+0

$中的值!不保證是任何東西,除非在函數調用之後立即檢查。失敗和b。聲稱使用errno。所以任何被造的人都會做錯事。 – 2009-06-25 18:13:26

+0

就像一個供參考,許多人認爲使用圖書館「死」非常treif(又名非猶太教:)的東西。 使用_error/_errors標誌和適當的訪問器方法(理想情況下,一個用於快速真/假檢查,另一個用於打印錯誤列表)。最好在物件層面上做到這一點:) – DVK 2009-06-26 12:51:27

+0

@DVK我強烈反對。它更適合圖書館拋出異常,只要它們真的非常特殊,並且你記錄了你將如何處理錯誤並保持一致。爲什麼?圖書館的用戶將想知道何時出現錯誤。如果有的話,他們通常會死亡。這導致在任何地方編寫「$ obj->方法或死於$ obj->錯誤」。你會很懶,忘記和錯過一個錯誤。例外情況意味着您只需在要從錯誤中恢復的地方添加特殊代碼即可。使用autodie一段時間,你會看到。 – Schwern 2009-06-27 18:38:48

3

設置$!是好的,但:

  • 你應該在你的函數
  • 結束做到這一點,你應該返回不同的值都表示出現了錯誤
  • 你應該用你的操作系統的errno值而不是字符串用於設置
  • 檢查代碼需要檢查該值是否應該立即在功能失敗時立即執行(並且只有在功能指示失敗時)

需要記住的是die使用$!中的值爲它的退出代碼(只要它不是零)。

0

如果您只有一個變量來存儲錯誤,那麼在檢查錯誤變量的狀態之前,如果在程序中發生了多個錯誤,則會出現問題。如果你能幫上忙,那就值得避免。

謝謝你在Perl中可以幫到你。一個非常好的解決方案是使用來自Error.pm的面向對象的異常處理。此模塊將允許你寫try/catch塊,像這樣:

try { 
    some code; 
    code that might thrown an exception; 
    more code; 
    return; 
} 
catch Error with { 
    my $ex = shift; # Get hold of the exception object 
    # handle the exception; 
}; 

CPAN documentation該模塊是相當不錯的,並有一個Perl.com文章的主題了。

0

$!有很多警告,作爲一個全局變量,有很多函數會分配給它(其中一些是Perl調用的C函數),我會簡單地拋出一個異常(在Perl中意味着死亡),並讓用戶捕獲它。因此,而不是寫:

$obj->foo or die $!; 
$obj->bar or die $!; 
$obj->baz or die $!; 

甚至

$obj->foo or die $obj->error; 
$obj->bar or die $obj->error; 
$obj->baz or die $obj->error; 

,你可以只寫

$obj->foo; 
$obj->bar; 
$obj->baz; 

,並知道如果有你的它被告知一個錯誤。此外,你上面的任何人都將被告知並可以將其捕獲。因爲這是最常見的情況,所以用戶不需要記住它並一遍又一遍地輸入。

如果您想忽略或從錯誤中恢復,只需使用eval BLOCK即可。

eval { $obj->foo }; # don't care if it works or not 
eval { $obj->bar } or do { ...something when it doesn't work... }; 

由於這是它應該是用戶必須記住添加更多的代碼,並做更多的工作的例外情況。

此方法的示例包括DBI's RaiseError flag,它僅在默認情況下爲關閉狀態而關閉,以及美妙的autodie模塊。

相關問題