2010-04-13 2 views
8

Я играю с обработкой ошибок и получаю небольшую проблему. Я подключаюсь к базе данных с помощью модуля DBI.Perl: ошибка catch без матрицы

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

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

DBI connect(...) failed: ORA-12154: TNS:could not resolve the connect identifier specified (DBD ERROR: OCIServerAttach) at ...

Как бы я идти о ловле это?

Я попытался с помощью $SIG{__DIE__} так:

local $SIG{__DIE__} = sub { 
    my $e = shift; 
    print "Error: " .$e; 
}; 

Это на дне моего основного файла, в этом файле я также производится вызов подпрограммы, которая доступна в модуле самостоятельно. Я также попытался поставить этот кусок кода на день моего модуля, но он по-прежнему печатает ошибку без

Error:

перед ним.

ответ

3

Хорошо, нашел решение, по-видимому, мне нужно было __WARN__ вместо __DIE__ и этого куска кода, необходимого, чтобы быть в верхней части файла, до того, где была брошена ошибка, в отличие от примера я прочитал сказал :)

+3

Правильно, это было предупреждение, а не смерть, и сначала нужно установить обработчик. Вы можете установить его в любом модуле, если вы завернете его в 'BEGIN {}'. – Ether

+0

прочитайте, что, благодарю вас за подтверждение. – Pmarcoen

2

В DBI есть много переключателей, таких как PrintError, RaiseError и т. Д., Которые вы можете настроить. См http://search.cpan.org/perldoc?DBI

+0

Хм не существует более общего решения? Так что я могу поймать все другие ошибки с помощью 1 функции. Я мог бы использовать множество модулей, которые имеют множество способов вывода ошибок, я хочу быть независимым от этого. – Pmarcoen

+0

DBI также имеет метод HandleError. Или, если вы установите PrintError на false, RaiseError на true, вы должны вызвать обработку ошибок (Pmarcoen's). – runrig

0

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

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

8

DBI connect(...) failed: ORA-12154: TNS:could not resolve the connect identifier specified (DBD ERROR: OCIServerAttach) at ...

How would I go about catching this ?

Чтобы поймать и справиться с этим уровнем ошибки, используйте eval в блочной форме, "eval {...}". Это поймает любую смерть, которая произойдёт в подкоде. Если код внутри блока eval будет умирать, он установит $ @, и блок вернет false. Если код не умирает, $ @ будет установлен в ''.

Использование обработки сигналов через SIG {WARN} и SIG {DIE} является проблематичным, поскольку они являются глобальными, есть также условия гонки, которые следует учитывать (что произойдет, если я получу сигнал, когда я обрабатываю другой сигнал? Традиционные проблемы, основанные на сигнальных вычислениях). Вероятно, вы пишете однопоточный код, поэтому вы не беспокоитесь о проблемах параллелизма, связанных с множеством вещей, вызывающих смерть, но пользователь должен подумать (возможно, он отправит SIGKILL, когда вы пытаетесь открыть соединение DBI)

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

Вот базовый пример использования eval {...}.

my $dbh = eval { DBI->connect(@args) }; 
if ([email protected]) 
{ 
    #DBI->connect threw an error via die 
    if ([email protected] =~ m/ORA-12154/i) 
    { 
     #handle this error, so I can clean up and continue 
    } 
    elsif ([email protected] =~ m/SOME \s* other \s* ERROR \s+ string/ix) 
    { 
     #I can't handle this error, but I can translate it 
     die "our internal error code #7"; 
    } 
    else 
    { 
     die [email protected]; #re-throw the die 
    } 
} 

Есть некоторые незначительные проблемы с использованием eval таким образом, имея отношение к глобальной области $ @. Отличное объяснение имеет страница Try::Tiny cpan. Попробуйте :: Tiny обрабатывает минимальную настройку Try/catch block и обрабатывает локализацию $ @ и обработку других случаев.

+0

Так было с первого раза, но eval, однако, не уловил предупреждений, о которых я хотел сообщить. Поэтому я должен использовать SIG {WARN}. – Pmarcoen

2

Включите это в SIG{__DIE__} блоке:

### Check if exceptions being caught. 
return if $^S; 

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

Смежные вопросы