Я написал программу perl, которая внутренне вызывает три модуля perl. Мой руководитель после рассмотрения кода попросил меня добавить глобальную обработку исключений. Я не понимал, что он имел в виду под этим. Он также сказал использовать Eval для выполнения этого. Я не уверен, как использовать Eval, чтобы он ловил любое исключение в модуле perel perl. Может ли кто-нибудь помочь мне, предоставив ссылки или предоставив объяснения? Спасибо заранее.обработка исключений глобального уровня в perl
ответ
Для каждой программы он хочет, чтобы у меня была обработка исключений, где, если что-то пойдет не так, оно будет подсвечено, и нам будет легко отлаживаться.
Когда происходит неперехваченное исключение, оно печатается в 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
Проблема, которую вы задаете, кажется неточной. «Глобальный» и 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.
Это может помочь: [Как лучше всего обрабатывать исключения в Perl?] (Http://stackoverflow.com/questions/4006267/what-is-the-best-way-to-handle-exceptions-in -perl) – Amadan
Думаю, вам, вероятно, придется спросить своего руководителя! Насколько мне известно, глобальная обработка исключений в Perl включает в себя запись обработчика 'die', присваивая подпрограмму' $ SIG {__ DIE __} '(как описано в [perlvar] (http://perldoc.perl.org/ perlvar.html # General-переменные)). И это действительно хорошо для отладки. С другой стороны, 'eval' позволяет обрабатывать ошибки только в одном блоке кода. Я думаю, если бы у вас была 'main()' подпрограмма, которая выполняла всю программу, как в C, тогда вы могли бы поместить ее в 'eval {main(); } 'block, но я не уверен, что вижу смысл. – Borodin
У вас есть отличный совет и информация из [Amadan] (http://stackoverflow.com/users/240443/amadan) и [Бородин] (http://stackoverflow.com/users/622310/borodin), чей комментарий также выражает тот факт, что не совсем ясно, какова ваша ситуация; «Глобальная обработка исключений» - это странный термин для меня. Вот несколько вопросов: Сколько/часто вы вызываете функции из этих модулей? На каком уровне - зарыты глубоко внутри подводных лодок или в 'main ::'? Какие модули? Каков размер и структура всего проекта? В двух словах, я имею в виду. – zdim