Учебники

Perl — обработка ошибок

Выполнение и ошибки всегда идут вместе. Если вы открываете файл, который не существует. тогда, если вы не справились с этой ситуацией должным образом, значит, ваша программа плохого качества.

Программа останавливается, если происходит ошибка. Таким образом, правильная обработка ошибок используется для обработки различных типов ошибок, которые могут возникнуть во время выполнения программы, и предпринять соответствующие действия вместо полной остановки программы.

Вы можете определить и уловить ошибку несколькими различными способами. Очень легко отлавливать ошибки в Perl и затем правильно их обрабатывать. Вот несколько методов, которые можно использовать.

Оператор if

Оператор if является очевидным выбором, когда вам нужно проверить возвращаемое значение из оператора; например —

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

Здесь переменная $! возвращает фактическое сообщение об ошибке. В качестве альтернативы, мы можем сократить выражение до одной строки в ситуациях, когда это имеет смысл сделать; например —

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

Функция разве что

Функция разве является логической противоположностью операторам if: они могут полностью обойти статус успеха и выполняться только в том случае, если выражение возвращает false. Например —

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

Оператор Тогда лучше всего использовать, когда вы хотите вызвать ошибку или альтернативу, только если выражение не выполнено. Это утверждение также имеет смысл, когда используется в однострочном утверждении —

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

Здесь мы умираем только в случае сбоя операции chdir, и она хорошо читается.

Троичный оператор

Для очень коротких тестов вы можете использовать условный оператор ?:

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

Здесь не совсем понятно, чего мы пытаемся достичь, но эффект такой же, как при использовании оператора if или else . Условный оператор лучше всего использовать, когда вы хотите быстро вернуть одно из двух значений в выражении или операторе.

Функция предупреждения

Функция warn только выдает предупреждение, сообщение выводится в STDERR, но никаких дальнейших действий не предпринимается. Таким образом, это более полезно, если вы просто хотите напечатать предупреждение для пользователя и продолжить работу —

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

Функция умирает

Функция die работает так же, как warn, за исключением того, что она также вызывает exit. В обычном скрипте эта функция немедленно прекращает выполнение. Вы должны использовать эту функцию, если она бесполезна, если в программе есть ошибка —

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

Ошибки внутри модулей

Есть две разные ситуации, с которыми мы должны справиться —

  • Сообщение об ошибке в модуле, которая указывает имя файла и номер строки модуля — это полезно при отладке модуля или когда вы специально хотите вызвать ошибку, связанную с модулем, а не со сценарием.

  • Сообщение об ошибке в модуле, который цитирует информацию о вызывающем абоненте, чтобы вы могли отладить строку в скрипте, вызвавшем ошибку. Ошибки, возникающие таким образом, полезны для конечного пользователя, потому что они выделяют ошибку по отношению к исходной строке вызывающего скрипта.

Сообщение об ошибке в модуле, которая указывает имя файла и номер строки модуля — это полезно при отладке модуля или когда вы специально хотите вызвать ошибку, связанную с модулем, а не со сценарием.

Сообщение об ошибке в модуле, который цитирует информацию о вызывающем абоненте, чтобы вы могли отладить строку в скрипте, вызвавшем ошибку. Ошибки, возникающие таким образом, полезны для конечного пользователя, потому что они выделяют ошибку по отношению к исходной строке вызывающего скрипта.

Функции warn и die работают немного иначе, чем вы ожидаете при вызове из модуля. Например, простой модуль —

package T;

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

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

Когда вызывается из скрипта, как показано ниже —

use T;
function();

Это даст следующий результат —

Error in module! at T.pm line 9.

Это более или менее то, что вы могли ожидать, но не обязательно то, что вы хотите. С точки зрения программиста модуля, информация полезна, потому что она помогает указать на ошибку в самом модуле. Для конечного пользователя предоставленная информация довольно бесполезна, а для всех, кроме опытного программиста, она абсолютно бессмысленна.

Решением для таких проблем является модуль Carp, который предоставляет упрощенный метод для сообщения об ошибках в модулях, которые возвращают информацию о вызывающем скрипте. Модуль Carp предоставляет четыре функции: карп, cluck, croak и confess. Эти функции обсуждаются ниже.

Функция карпа

Функция carp является основным эквивалентом warn и печатает сообщение в STDERR без фактического выхода из сценария и печати имени сценария.

package T;

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

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

Когда вызывается из скрипта, как показано ниже —

use T;
function();

Это даст следующий результат —

Error in module! at test.pl line 4

Функция щелчка

Функция cluck — это своего рода карп с наддувом, она следует тому же базовому принципу, но также печатает трассировку стека всех модулей, которые привели к вызову функции, включая информацию об исходном скрипте.

package T;

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

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

Когда вызывается из скрипта, как показано ниже —

use T;
function();

Это даст следующий результат —

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

Функция квака

Функция квака эквивалентна смерти , за исключением того, что она сообщает вызывающему на один уровень выше. Как и die, эта функция также выходит из сценария после сообщения об ошибке в STDERR —

package T;

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

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

Когда вызывается из скрипта, как показано ниже —

use T;
function();

Это даст следующий результат —

Error in module! at test.pl line 4

Как и в случае с карпом, применяются те же основные правила, что и в отношении информации о строках и файлах, в соответствии с функциями warn и die.

Функция признания

Функция признания похожа на щелчок ; он вызывает die, а затем печатает трассировку стека вплоть до исходного сценария.

package T;

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

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

Когда вызывается из скрипта, как показано ниже —

use T;
function();

Это даст следующий результат —