Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

CGI-программирование с самого начала. Обработка ошибок открытия файлов #1


Уважаемые подписчики!

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

http://www.subscribe.ru/archive/inet.webbuild.perlcgi

В этом выпуске мы рассмотрим обработку ошибок при работе с файлами в Perl-скриптах.

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

При этом в отличие, скажем, от языка BASIC, в котором ошибки при работе с файлами по умолчанию являются фатальными и приводят к аварийной остановке работы программы, функции работы с файлами в Perl (скажем, open) просто возвращают "успешность" выполненной операции в качестве результата. Никакой фатальной ошибки при этом не происходит и работа скрипта не останавливается. Поэтому задача обработки ошибок при работе с файлами ложится на программиста.

С одной стороны, это может показаться не очень хорошей идеей, зато с другой - позволяет обрабатывать такие ошибки более гибко: можно обрабатывать файловые ошибки "а-ля BASIC" (как чаще всего и делается), а можно, при желании и/или необходимости, реализовать более "интеллектуальный" подход :-)

Обработка ошибки открытия файла как фатальной

В большинстве случаев бывает достаточно обрабатывать ошибку открытия скриптом файла как фатальную, с аварийным завершением работы скрипта и записью сообщения об ошибке в журнал (лог) ошибок.

Для "вызова" фатальной ошибки в Perl есть особая функция - die ("умереть"):

die СООБЩЕНИЕ;

Она выполняет аварийное завершение работы скрипта и позволяет записать заданное сообщение об ошибке в журнал ошибок веб-сервера (вернее, она просто выводит сообщение в "стандартный поток ошибок" STDERR, а уже веб-сервер записывает его в свой лог ошибок), которое затем сможет прочитать администратор сайта, определить и устранить причину, вызывающую ошибку.

Как мы уже знаем, функция open возвращает ненулевое значение в случае успеха и "не определено" - в случае ошибки. Поэтому обработку ошибки открытия файла можно организовать следующим образом:

if (!defined (open(FILE, "datafile"))) {die "can't open file!";};

Это выражение либо успешно откроет файл с именем datafile, либо вызовет фатальную ошибку с сообщением "can't open file!" в журнал ошибок. Таким образом, дальнейший код скрипта (после этого выражения) может быть "уверен", что файл успешно открылся.

А теперь сделаем сообщение об ошибке более информативным - ведь ошибки открытия файлов могут быть разные (нет файла, нет достаточных прав доступа и т.п.) Для диагностики желательно бы знать, какая именно ошибка произошла. Функция open в случае ошибки открытия файла возвращает в специальной переменной $! конкретную информацию об ошибке, поэтому вставим значение этой переменной в сообщение об ошибке:

if (!defined (open(FILE, "datafile"))) {die "can't open file: $!";};

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

Обычно "обработчик ошибки" организуют еще проще, в форме выражения такого вида:

open(FILE, "datafile") || die("can't open file $!");

или такого:

open FILE, "datafile" or die "can't open file $!";

Именно такой вариант рекомендуется и в докементации к Perl.

На первый взгляд может быть совершенно непонятно, как такое выражение может работать: ведь оно по сути представляет из себя просто логическое выражение "или" с двумя аргументами - результатами выполнения функций open и die. Никаких ветвлений и условий здесь на первый взгляд нет. Однако следует заметить, что Perl вычисляет логические выражения слева направо до тех пор, пока результат выражения не станет определен и без вычисления значений дальнейших его "членов". В данном случае мы имеем логическое выражение "или", значение которого равно "1", если хотя бы один из его аргументов имеет значение "1" (т.е. в данном случае - ненулевое и не undefined). Если открытие файла произошло успешно, то функция open вернет ненулевое значение, при этом значение всего выражения станет определено независимо от результата вычисления значений других аргументов, его "обработка" прекратится и до функции die (и до фатальной ошибки) дело просто не дойдет :-)

Отметим, что само выражение выглядит довольно символично: "открыть или умереть!" :-)

Вообще, в отличие от "классических" языков программирования, где программа по сути состоит из операторов, в языке perl программа состоит именно из выражений - математических, логических... В частном распространенном случае, когда значение выражения ничему не присваивается (отсутствует левая часть), это выражение внешне выглядит как оператор с аргументами. Однако это не так. Скажем,

print "text";

- это не оператор вывода, а функция вывода, значение которой просто в данном случае ничему не присваивается (а зачем?).

С точки зрения Perl допустим даже такой код:

1+2; 2+3; 3 or 4;

Этот код, конечно же, не имеет практического смысла, но и ошибки не вызовет.

В следующем выпуске рассылки мы рассмотрим, как можно организовать более "интеллектуальную" обработку ошибок открытия файлов в CGI-скриптах применительно к конкретным ситуациям.

Также напоминаем Вам, что на нашем сайте рассылки

http://www.cgi-scripts.info/

Вы сможете найти статьи по программированию CGI-скриптов на Perl, а на нашем "старом" сайте

http://www.angel07.webservis.ru/

- статьи по вопросам веб-хостинга и его особенностям.

На сегодня все. До следующих встреч. :-)
Успехов!


Андрей
angel07@inbox.ru

В избранное