Perl - obsługa błędów

Wykonanie i błędy zawsze idą w parze. Jeśli otwierasz plik, który nie istnieje. wtedy jeśli nie poradziłeś sobie z tą sytuacją poprawnie, twój program zostanie uznany za złej jakości.

Program zatrzymuje się, jeśli wystąpi błąd. Tak więc odpowiednia obsługa błędów jest używana do obsługi różnego rodzaju błędów, które mogą wystąpić podczas wykonywania programu i podjęcia odpowiednich działań zamiast całkowitego zatrzymania programu.

Możesz zidentyfikować i złapać błąd na wiele różnych sposobów. Bardzo łatwo jest wychwycić błędy w Perlu, a następnie odpowiednio je obsłużyć. Oto kilka metod, które można zastosować.

Instrukcja if

Plik if statementjest oczywistym wyborem, gdy trzeba sprawdzić wartość zwracaną z instrukcji; na przykład -

if(open(DATA, $file)) {
   ...
} else {
   die "Error: Couldn't open the file - $!";
}

Tutaj zmienna $! zwraca rzeczywisty komunikat o błędzie. Alternatywnie, możemy zredukować instrukcję do jednej linii w sytuacjach, w których ma to sens; na przykład -

open(DATA, $file) || die "Error: Couldn't open the file $!";

Funkcja chyba że

Plik unlessfunkcja jest logicznym przeciwieństwem instrukcji if: może całkowicie ominąć status sukcesu i zostać wykonana tylko wtedy, gdy wyrażenie zwróci false. Na przykład -

unless(chdir("/etc")) {
   die "Error: Can't change directory - $!";
}

Plik unlessjest najlepiej używana, gdy chcesz zgłosić błąd lub alternatywę tylko wtedy, gdy wyrażenie zawiedzie. Instrukcja ma również sens, gdy jest używana w instrukcji jednowierszowej -

die "Error: Can't change directory!: $!" unless(chdir("/etc"));

Tutaj umieramy tylko wtedy, gdy operacja chdir się nie powiedzie i ładnie się czyta.

Operator trójskładnikowy

W przypadku bardzo krótkich testów możesz użyć operatora warunkowego ?:

print(exists($hash{value}) ? 'There' : 'Missing',"\n");

Nie jest tu do końca jasne, co próbujemy osiągnąć, ale efekt jest taki sam, jak użycie pliku if lub unlesskomunikat. Operatora warunkowego najlepiej używać, gdy chcesz szybko zwrócić jedną z dwóch wartości w wyrażeniu lub instrukcji.

Funkcja ostrzeżenia

Funkcja ostrzeżenia po prostu generuje ostrzeżenie, komunikat jest drukowany do STDERR, ale nie są podejmowane żadne dalsze działania. Jest to więc bardziej przydatne, jeśli chcesz po prostu wydrukować ostrzeżenie dla użytkownika i kontynuować resztę operacji -

chdir('/etc') or warn "Can't change directory";

Funkcja matrycy

Funkcja matrycy działa podobnie jak warn, z tą różnicą, że wywołuje również wyjście. W normalnym skrypcie ta funkcja powoduje natychmiastowe przerwanie wykonywania. Powinieneś użyć tej funkcji na wypadek, gdyby nie było sensu kontynuować, jeśli w programie wystąpił błąd -

chdir('/etc') or die "Can't change directory";

Błędy w modułach

Są dwie różne sytuacje, z którymi powinniśmy sobie poradzić -

  • Zgłaszanie błędu w module, który cytuje nazwę pliku modułu i numer wiersza - jest to przydatne podczas debugowania modułu lub gdy konkretnie chcesz zgłosić błąd związany z modułem, a nie ze skryptem.

  • Zgłaszanie błędu w module, który cytuje informacje o dzwoniącym, aby można było debugować wiersz w skrypcie, który spowodował błąd. Błędy zgłoszone w ten sposób są przydatne dla użytkownika końcowego, ponieważ podkreślają błąd w odniesieniu do linii źródłowej skryptu wywołującego.

Plik warn i diefunkcje działają nieco inaczej, niż można by oczekiwać, gdy są wywoływane z poziomu modułu. Na przykład prosty moduł -

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   warn "Error in module!";
}
1;

W przypadku wywołania ze skryptu takiego jak poniżej -

use T;
function();

To da następujący wynik -

Error in module! at T.pm line 9.

To mniej więcej to, czego mógłbyś się spodziewać, ale niekoniecznie to, czego chcesz. Z punktu widzenia programisty modułów informacje są przydatne, ponieważ pomagają wskazać błąd w samym module. Dla użytkownika końcowego podane informacje są dość bezużyteczne, a dla wszystkich, z wyjątkiem zatwardziałego programisty, są całkowicie bezcelowe.

Rozwiązaniem takich problemów jest moduł Carp, który zapewnia uproszczoną metodę raportowania błędów w modułach zwracających informacje o skrypcie wywołującym. Moduł Karp zapewnia cztery funkcje: karp, gdakanie, rechotanie i wyznanie. Funkcje te omówiono poniżej.

Funkcja karpia

Funkcja karp jest podstawowym odpowiednikiem ostrzeżenia i wyświetla wiadomość do STDERR bez faktycznego zamykania skryptu i drukowania nazwy skryptu.

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   carp "Error in module!";
}
1;

W przypadku wywołania ze skryptu takiego jak poniżej -

use T;
function();

To da następujący wynik -

Error in module! at test.pl line 4

Funkcja Cluck

Funkcja cluck jest rodzajem superdoładowanego karpia, działa zgodnie z tą samą podstawową zasadą, ale także drukuje ślad stosu wszystkich modułów, które doprowadziły do ​​wywołania funkcji, w tym informacje o oryginalnym skrypcie.

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp qw(cluck);

sub function {
   cluck "Error in module!";
}
1;

W przypadku wywołania ze skryptu takiego jak poniżej -

use T;
function();

To da następujący wynik -

Error in module! at T.pm line 9
   T::function() called at test.pl line 4

Funkcja rechotania

Plik croak funkcja jest równoważna die, z wyjątkiem tego, że zgłasza dzwoniącego o jeden poziom wyżej. Podobnie jak die, ta funkcja również zamyka skrypt po zgłoszeniu błędu do STDERR -

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   croak "Error in module!";
}
1;

W przypadku wywołania ze skryptu takiego jak poniżej -

use T;
function();

To da następujący wynik -

Error in module! at test.pl line 4

Podobnie jak w przypadku karpia, obowiązują te same podstawowe zasady dotyczące uwzględniania informacji o liniach i plikach zgodnie z funkcjami ostrzeżenia i matrycy.

Funkcja wyznania

Plik confess funkcja jest jak cluck; wywołuje die, a następnie drukuje ślad stosu aż do skryptu źródłowego.

package T;

require Exporter;
@ISA = qw/Exporter/;
@EXPORT = qw/function/;
use Carp;

sub function {
   confess "Error in module!";
}
1;

W przypadku wywołania ze skryptu takiego jak poniżej -

use T;
function();

To da następujący wynik -

Error in module! at T.pm line 9
   T::function() called at test.pl line 4