#error-handling #sas
#обработка ошибок #sas
Вопрос:
У меня ожидаемая ошибка с amp;syserr.
of 1020
. При возникновении ошибки программа завершает работу со следующим сообщением:
FATAL: Unrecoverable I/O error detected in the execution of the DATA step program.
Aborted during the EXECUTION phase.
Я знаю, в чем проблема, и для нее нет решения. Однако, поскольку я знаю, что вызывает проблему, я хочу предупредить пользователя о том, как это исправить, до завершения работы программы.
То есть между возникновением ошибки и прерыванием программы я хочу выполнить некоторый код.
Я прочесал Интернет и не смог найти ничего, что говорило бы, что это невозможно сделать. На самом деле, многие ответы на SO подразумевали, что это можно сделать. Но я понятия не имею, как.
Комментарии:
1. Как вы запускаете программу? Интерактивный? Пакет?
2. Я думаю, технически интерактивный. Я нахожусь в оконной среде SAS, используя улучшенный редактор. Я выбираю инструкции, которые хочу выполнить, а затем нажимаю «Отправить». Код, который выдает ошибку, существует в макросе.
3. Когда вы говорите «прервано», вы просто имеете в виду, что этап передачи данных завершается? Или SAS завершается? Или макрос завершается неправильно?
4. Код прекращает выполнение, и управление возвращается расширенному редактору. В журнал записывается сообщение об ОШИБКЕ. В идеале я хотел бы выполнить код между возникновением ошибки и записью сообщения об ошибке. Я знаю, что в SAS нет конструкции try / catch, поэтому я надеюсь, что может существовать механизм типа «on error goto». antonis.de/qbebooks/gwbasman/onerror.html
5. После того, как это произойдет, если вы отправите еще один небольшой шаг С ДАННЫМИ, это сработает? Или вся ваша интерактивная сессия в значительной степени нарушена, и вам нужно закрыть SAS и перезапустить?
Ответ №1:
Поскольку вы знаете, что установлен параметр amp;syserr, одним из вариантов было бы написать свой собственный макрос %onError, что-то вроде:
%macro OnError(debug=0);
%if amp;syserr ne 0 %then %do;
%*blah blah blah;
%end;
%mend OnError;
Итак, ваш код выглядит следующим образом:
data want;
set have;
oops;
run;
%OnError()
Обратите внимание, что amp;syserr сбрасывается после каждой границы шага, поэтому вам нужно протестировать его сразу после подозрительного шага. Существуют другие переменные макроса с кодами возврата, которые сохраняются.
Если ошибка была достаточно серьезной, чтобы SAS перешла в режим проверки синтаксиса (установите obs = 0 и noreplace), вам пришлось бы сделать больше для восстановления. Но я думаю, что по умолчанию в interactive SAS это отключено.
Комментарии:
1. Я думаю, что если бы это была обычная ошибка, это было бы совершенно правильно. Однако я думаю, что ошибка, на которую он ссылается, не следует за этими строками — это скорее ошибка в SAS code supervisor или что-то еще, где она перегружается. Хотя и не уверен.
2. Это позволяет мне выполнять код, хотя я не могу найти способ предотвратить прерывание. Например, я могу написать сообщение в журнал, в котором более подробно описывается, почему программа прерывается. Кажется, я не в состоянии предотвратить прерывание.
3. Согласен, это не позволит избежать прерывания или сообщения об ошибке. Это может быть использовано для «восстановления» в смысле повторной попытки выполнения шага (если это была проблема с сетью или аналогичная) или запуска альтернативного шага, или отправки кому-либо электронного письма и т.д. Но это не похоже на настоящую попытку … поймать. Я думаю, что вы застряли, пытаясь либо избежать ошибки, либо восстановиться после возникновения ошибки.
Ответ №2:
Хотя это неуклюже, желаемого результата можно достичь с помощью операторов %LABEL и %GOTO.
Необходимо учитывать, что
«метка, которая является целью инструкции %GOTO, должна существовать в текущем макросе; вы не можете перейти к метке в другом макросе с помощью инструкции %GOTO».
Поскольку ошибка возникает в коде, уже содержащемся в макросе, отдельный макрос не может использоваться для обработки события ошибки. (SAS рекомендует не создавать макросы внутри других макросов).
Комментарии:
1. Хороший улов. Я не смог придумать пример, который эмулирует мою проблему, поэтому я удалил пример, на который вы ссылаетесь. Мы надеемся, что ваш ответ вместе с %goto /% label должен предоставить достаточную информацию для процветания.