我有一个非常大的SAS程序,包含大约50个子程序,每个子程序都有很多步骤。目前,无论是否有错误,它都会一直运行到完成。我要求它在发生错误时停止并退出。
注意(我相信)SYSERR宏不适用于此任务,因为我需要在每个步骤结束时检查SYSERR(例如,在每个DATA或PROC步骤之后),因为在每个步骤边界后重置SYSERR ;这将是一项非常耗时且容易出错的任务,因为我的50个子程序中每个都有数千个不同的步骤边界。
我设想的解决方案类型包括检查每个(50个)子程序在运行后立即生成的日志文件,然后在日志文件中出现错误时停止(或继续执行下一个程序)子程序,如果没有错误)。然而,我无法想象如何做到这一点。 非常感谢提前。
答案 0 :(得分:0)
我相信你检查日志的解决方案是好的。 因为您可以过滤“WARNING”和“ERROR”或“ERROR:”之类的单词。 您可以将日志复制到excel并过滤行是否包含这些错误关键字。
但是,我在这里有一个SAS解决方案,
1)使用proc printto创建日志 2)关闭proc printto重定向 3)使用SAS自动分析日志
以下是宏功能的代码:
/**
*
* @dev Function to create a log for a program
* @param job The name of the job to be logged
*
*/
%macro runjob(job /*Enter the name of the job to log Ex: myjob*/);
option fullstimer;
%let runjob=%sysfunc(compress(&job._%sysfunc(datetime(),b8601dt)));
data _null_;
call symputx("runjob","&runjob.",'G');
run;
filename logfile "C:\LOG\&runjob..log";
proc printto log=logfile new;
run;
%mend runjob; /* %runjob(myjob); */
/**
*
* @dev Funtion to check if a table is empty
* @param inset The name of dataset to be checked
*
*/
%macro checkTableIfEmpty(inset /* Write the name of your dataset (ex: checklog) */);
%let dsid = %sysfunc (open(&inset));
%if &dsid ge 0 %then
%let dsid = 1;
%let anyobs = %sysfunc (attrn(&dsid,ANY));
%let dsid = %sysfunc (close(&dsid));
%put anyobs=&anyobs;
%if &anyobs = 1 %then
%do;
data _null_;
call symputx('checkTableIfEmpty',0,'G');
run;
%end;
%else
%do;
data _null_;
call symputx('checkTableIfEmpty',1,'G');
run;
%end;
%mend checkTableIfEmpty; /* %checkTableIfEmpty(checklog); */
/**
*
* @dev Function to filter a log file from SAS with words like "warning" and "error"
* @param inp The pathname of the log to be checked
*
*/
%macro checkLog(inp /* Write the pathname of the log to be checked (ex: myjob_20170818T161545.log) */);
data empty_marker;
length MSG $200;
MSG='No error(s)/warning(s).';
run;
DATA CHECKLOG;
LENGTH ROWS $200;
LABEL ROWS = 'Messages from LOG';
INFILE "&inp" TRUNCOVER;
INPUT ROWS &;
LINE = _N_;
IF SUBSTR(ROWS,1,5)='ERROR' OR SUBSTR(ROWS,1,7)='WARNING' THEN
OUTPUT;
RUN;
%checkTableIfEmpty(checklog);
ODS HTML BODY="C:\LOG\log.html" STYLE=sasweb;
TITLE1 "Messages from LOG";
%if &checkTableIfEmpty = 0 %then
%do;
proc sql;
select distinct(rows) from checklog;
run;
%end;
%else
%do;
proc print data=empty_marker;
run;
%end;
ODS HTML CLOSE;
%mend checkLog; /* %checkLog(c:\LOG\myjob_20170818T161545.log); */
然后,您可以在类似
的程序中使用这些功能%let jobname=myjob;
/* START */
%runjob(&jobname);
...
/*END*/
proc printto;
run;
%checkLog(C:\LOG\&runjob..log);
您将在C:\ LOG \ LOG.html
中获得一个html文件Messages from LOG
ERROR: Ambiguous reference, column DateSent is in more than one table.
ERROR: Ambiguous reference, column Operation_date is in more than one table.
ERROR: Expression using equals (=) has components that are of different data types.
ERROR: Expression using less than or equal (<=) has components that are of different data types.
由于“不同”的选择,删除了重复行。 使用每个子程序的每个日志进行调试会非常容易。
此致