Perl: зафиксируйте ошибку без, умирают

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

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

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

Подключение DBI (...) перестало работать: РТЫ 12154: TNS:could не разрешают указанный идентификатор подключения (ОШИБКА DBD: OCIServerAttach) в...

Как я пошел бы о ловле этого?

Я пытался использовать $SIG{__DIE__} как так:

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

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

Ошибка:

перед ним.

8
задан Pmarcoen 18 September 2012 в 11:46
поделиться

5 ответов

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

3
ответ дан 5 December 2019 в 10:40
поделиться

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

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

0
ответ дан 5 December 2019 в 10:40
поделиться

DBI connect ( ...) не удалось: ORA-12154: TNS: не удалось разрешить указанный идентификатор подключения (ОШИБКА DBD: OCIServerAttach) в ...

Как мне поймете это?

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

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

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

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

my $dbh = eval { DBI->connect( @args) };
if ( $@ )
{
    #DBI->connect threw an error via die
    if ($@ =~ m/ORA-12154/i )
    {
        #handle this error, so I can clean up and continue
    }
    elsif ( $@ =~ 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 $@; #re-throw the die
    }
}

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

8
ответ дан 5 December 2019 в 10:40
поделиться

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

2
ответ дан 5 December 2019 в 10:40
поделиться

Включите это в свой блок SIG {__ DIE __} :

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

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

3
ответ дан 5 December 2019 в 10:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: