2016-02-29 1 views
0

Я написал программу perl, которая внутренне вызывает три модуля perl. Мой руководитель после рассмотрения кода попросил меня добавить глобальную обработку исключений. Я не понимал, что он имел в виду под этим. Он также сказал использовать Eval для выполнения этого. Я не уверен, как использовать Eval, чтобы он ловил любое исключение в модуле perel perl. Может ли кто-нибудь помочь мне, предоставив ссылки или предоставив объяснения? Спасибо заранее.обработка исключений глобального уровня в perl

+1

Это может помочь: [Как лучше всего обрабатывать исключения в Perl?] (Http://stackoverflow.com/questions/4006267/what-is-the-best-way-to-handle-exceptions-in -perl) – Amadan

+4

Думаю, вам, вероятно, придется спросить своего руководителя! Насколько мне известно, глобальная обработка исключений в Perl включает в себя запись обработчика 'die', присваивая подпрограмму' $ SIG {__ DIE __} '(как описано в [perlvar] (http://perldoc.perl.org/ perlvar.html # General-переменные)). И это действительно хорошо для отладки. С другой стороны, 'eval' позволяет обрабатывать ошибки только в одном блоке кода. Я думаю, если бы у вас была 'main()' подпрограмма, которая выполняла всю программу, как в C, тогда вы могли бы поместить ее в 'eval {main(); } 'block, но я не уверен, что вижу смысл. – Borodin

+0

У вас есть отличный совет и информация из [Amadan] (http://stackoverflow.com/users/240443/amadan) и [Бородин] (http://stackoverflow.com/users/622310/borodin), чей комментарий также выражает тот факт, что не совсем ясно, какова ваша ситуация; «Глобальная обработка исключений» - это странный термин для меня. Вот несколько вопросов: Сколько/часто вы вызываете функции из этих модулей? На каком уровне - зарыты глубоко внутри подводных лодок или в 'main ::'? Какие модули? Каков размер и структура всего проекта? В двух словах, я имею в виду. – zdim

ответ

1

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

Когда происходит неперехваченное исключение, оно печатается в STDERR. Ваше требование подсветки уже выполняется.

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

$ perl -e'sub f { die "bar" } f("foo")' 
bar at -e line 1. 

Добавление use Carp::Always; в ваши сценарии заставит стек трассировку быть предусмотрено также, предоставления дополнительной информации.

$ perl -e'use Carp::Always; sub f { die "bar" } f("foo")' 
bar at -e line 1. 
     main::f("foo") called at -e line 1 
0

Проблема, которую вы задаете, кажется неточной. «Глобальный» и eval несколько противоречивы, так как в его комментарии объясняется Borodin. Другой способ сделать что-то «глобальное» дается в ответе ikegami. Однако, поскольку упоминание eval- это, то здесь приведено краткое изложение его самого элементарного использования.

Вы используете eval на блоке кода (или выражении, но это не то, что вы хотите здесь). Если die выброшен где-либо внутри этого блока, то eval поймает, что в том смысле, что вы получите управление обратно, программа не просто умрет. Переменная [email protected] заполняется сообщением об ошибке. Затем вы можете допросить, что произошло, распечатать диагностику и, возможно, восстановить ошибку.

eval { run_some_code(@args) }; 
if ([email protected]) { 
    carp "Error in `run_some_code()`: [email protected] --"; 
    # Do further investigation, print, recover ... 
} 

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

Что касается «глобального» в вашем заявлении о проблемах, то вам приходит в голову, что вы используете eval на уровне main:: - оберните в него любые подсистемы, которые сами вызывают функции из модулей.

Важнейшая вещь об исключениях заключается в том, что они «пузырятся». Когда die (единственное исключение Perl) выбрасывается в sub, а вызывающий абонент не eval, он поднимается по цепочке звонков ... в конечном итоге появляется в main::, и если он не пойман (eval -ed) затем программа умирает. Таким образом, вы можете eval позвонить на верхний уровень в main:: и узнать, не произошло ли что-либо внизу.

eval { top_level_call(); }; 
if ([email protected]) { 
    warn "Error from somewhere in `top_level_call(): [email protected]"; 
} 

# Functions 
sub top_level_call { 
    # doing some work ... 
    another_sub(); 
    # doing more ... 
} 
sub another_sub { 
    # do work, no eval checks 
} 

Если ошибка запуская die происходит в another_sub() его обработки немедленно останавливается и управление возвращается к вызывающему абоненту, в top_level_call(). Поскольку этот суб не проверяет (там нет eval), его выполнение останавливается и в этой точке, и элемент управления возвращается к его вызывающему абоненту (в этом примере сам main::). Таким образом, он в конечном итоге попадает в main::, и eval. Здесь вы можете узнать об ошибках, и ваша программа не просто выйдет.

Возможно, именно это подразумевалось под «глобальным» обработкой исключений с использованием eval.

Вы можете сделать гораздо больше вдоль этих линий, если это то, что вам нужно делать. См. eval для стартеров. Обновите свой вопрос с разъяснениями, чтобы вы могли больше обсуждать здесь.

В практическом плане я бы сказал, что вы экипируете себя каким-то пониманием использования eval, а также некоторые «глобальные» сообщения об ошибках, а затем попросите своего руководителя пояснить и/или примеры, как предложено Borodin.