有没有一种方法可以让SAS在出现第一个警告或错误时停止?

24

SAS喜欢在警告和错误之后继续处理,所以我经常需要滚动回日志页面以查找问题。有更好的方法吗?我希望它能在第一次出现错误或警告时停止处理,这样我就可以修复问题并重试。

SAS 常常在出现警告和错误后依然继续处理,因此我常常需要浏览整个日志页面来查找问题。 有没有更好的方式?我希望它可以在第一个错误或警告出现时立即停下来,这样我就能够及时修正并尝试再次运行。

我看到SO上有关于编程SAS迁移的问题。 - whuber
5个回答

17

之前建议使用的ERRORS=1选项仅停止将ERROR消息写入日志。我建议使用另一个系统选项ERRORABEND,它可以阻止程序在大多数错误时继续处理。我不知道有哪个选项可以由于警告而终止处理,但我认为您可以添加以下宏来停止处理。

%macro check_for_errors;
   %if &syserr > 0 %then %do;
      endsas;
   %end;
%mend check_for_errors;

data test1;
    <data step code>
run;
%check_for_errors;

你可以在程序的每个步骤之后重复宏调用,这样它将在错误代码不为0时终止。


1
应该多了解一下 ERRORS= 选项...我删除了我的答案并更新了你的答案。 - Jay Corbett
3
有没有像ERRORABEND选项一样不会导致与 SAS 服务器断开连接的选项?我使用 EG 连接到外部 Unix 服务器,虽然在第一个错误处停止处理很好,但 ERRORABEND 会关闭与服务器的连接,在下一次运行时需要一段时间来重新建立连接。 - o.h
1
你也可以检查&syserrortext是否非空。我发现这个变量比&syserr更可靠。 - Jake Z

5
我最近一直在使用%runquit宏。对于批处理和交互式会话都很有效(不关闭会话,只停止运行代码)。
源自:http://www.cpc.unc.edu/research/tools/data_analysis/sas_to_stata/sas-macros/runquit.html 使用时,您只需在任何数据步骤或PROC末尾键入%runquit;,而不是键入常规的runquit语句即可。
%macro runquit;
  ; run; quit;
  %if &syserr. ne 0 %then %do;
     %abort cancel;
  %end;
%mend runquit;

Datastep用法:

data something; 
 * do some stuff;
%runquit;

PROC使用方法:

proc sql; 
  * do some stuff;
%runquit;

虽然阅读代码时不太美观,但这确实使得调试变得更加容易。


这似乎是一个不错的答案,但它会使企业指南停滞不前。程序一直在运行,但从未完成返回结果/错误到日志。它将停止程序继续运行并覆盖/创建其他数据集,所以我想它还是达到了主要目的。 - thelatemail
@thelatemail 我们正在迁移到一个环境,我将能够使用EG进行测试。一旦我有机会测试,我会更新的。 - Robert Penridge

3
一种选择是在整个代码中将run替换为run &g_cancelproc sql;替换为proc sql &g_noexec;。最初,&g_cancel&g_noexec的值都为空,因此会执行所有步骤。
当出现错误(无论是%sys_rc%sql_rc还是业务逻辑)时,设置&g_cancel为cancel,&g_noexec为noexec。
这应该会阻止任何后续步骤的运行-显然,对于必须运行的步骤(例如清理),可以省略宏变量或在执行纯宏步骤之前进行检查。
注意Enterprise Guide用户:唯一需要注意的是,如果您在同一个会话中运行多个代码项目,则需要在每个代码项目开始时重置错误术语,以免不相关的错误导致任何问题。

我认为你的意思是在第一句中将“run”替换为“run &cancel”。 - Stig Eide

2

作为对Rwill回答的补充:

如果您正在使用存储过程(STP),当错误发生时不向用户显示日志并删除“显示SAS日志”按钮也很好。

可以通过以下方式实现

%macro checkcc;
    options obs=max no$syntaxcheck;
    %if (&syscc gt 4) %then
        %do;
            data _null_;
                file _webout;
                put "<h3>Sorry, your request was not processed successfully.<h3>";
                rc = stpsrvset('program error', 0);
            run;
        %end;
    %let syscc=0;
%mend checkcc;
%checkcc;

来源: http://support.sas.com/kb/16/225.html

以下是我制作的增强版,仍以json格式显示错误信息。

%macro checkErrors;
    options obs=max no$syntaxcheck;
    %let old = %sysfunc(stpsrv_header(Content-type, application/json%str(;) charset=utf-8));
    %put &=syscc; %put &=syserr; %put &=sysrc; %put &=syswarningtext; %put &=syserrortext;
    %if (&syscc gt 4) %then %do;
        data _null_;
            file _webout;
            put '{';
            put '  "success":"false"';
            put '  ,"message":"' "&syserrortext" '"';
            put '  ,"syscc":"' "&syscc" '"';
            put '}';
            rc = stpsrvset('program error', 0);
            run;
        %end;
    %let syscc=0;
%mend checkErrors;
%checkErrors;

同时也有HTML版本:

%macro checkErrors_HTML;
    options obs=max no$syntaxcheck;
    %if (&syscc gt 4) %then %do;
        data _null_;
            file _webout;
            put '<!doctype html> ';
            put '<html> ';
            put '   <head> ';
            put '       <title>Error</title> ';
            put '   </head> ';
            put '   <body> ';
            put '       <h1>An Error Occured</h1>';
            put '       <p>' "&syserrortext" '</>';
            put '   </body>';
            put '</html>';
            rc = stpsrvset('program error', 0);
            run;
        %end;
    %let syscc=0;
%mend checkErrors_HTML;
%checkErrors_HTML;

非常好!你可能还想在其中加入%abortendsas;,这样程序的其余部分就不会不必要地运行了吧? - Allan Bowe
@AllanBowe 这不需要在程序中经常进行%checkErrors吗?我只是将%checkErrors放置在STP的最后,所以我不确定它是否还有用于中止。你怎么看? - stallingOne
如果程序执行到最后,那么无需中止。我只是在考虑一些我自己使用的情况(长时间运行的STP),在程序运行过程中能够中止而不向客户端发送错误信息将会非常方便。 - Allan Bowe
今天发现 - syscc=0 部分非常必要! - Allan Bowe

2
我经常做类似于RWill的事情,但我会将整个程序包装在一个宏中。在每个DATA步骤、PROC SQL、PROC SORT等之后,我都会检查错误代码(&SYSERR或&SQLRC)。如果它是非零的,我就跳到结尾。
更多细节和代码请参见:https://heuristically.wordpress.com/2012/02/09/return-codes-errors-sas/ 由于我们组织的批处理系统在一个SAS会话中独立运行程序,因此我无法使用RWill的endsas。

1
太好了!刚读了博客文章,正在尝试。多年来,我一直感到困惑的是SAS为什么不会自动这样工作。 快速问题:在检查PROC SQL错误时,我是否必须使用SQLRC变量,还是只有在我关心恢复SQL错误代码时才需要?看起来SYSERR也适用于PROC SQL,但我想再确认一下。再次感谢! - sparc_spread
1
@sparc_spread:如果您不关心在PROC SQL中处理错误,那么就不要检查错误代码。我能想到的一个情况是使用“drop table foo;”,而您并不关心表是否存在。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接