如何正确读取SAS宏循环中的错误代码?

问题描述 投票:0回答:1

我正在尝试构建 SAS 代码来查看过去的日志、重新运行失败的报告并通知重新运行状态。我正在使用&syscc。宏来检查我的重新运行尝试中是否存在错误,并在每次尝试之间重置它。但是,我在宏 %do 循环中使用 syscc 时遇到了问题,因为 syscc 没有显示正确的错误代码。 IE。它没有显示第一个循环的任何错误,尽管它应该显示,然后它无法重置回 0。(共享下面的代码段)。是否有使用 syscc 的替代方法或其他编写宏的方法?

%macro rerunner();
    %do i=1 %to &numrecs;
    %put &i;
    

        /*selecting a log and code*/
        proc sql;
            select cname into :  selected_code separated by ','
            from code_logs
            where rown=&i;
        quit;   
        proc sql;
            select lname into :  selected_log separated by ','
            from code_logs
            where rown=&i;
        quit;

        /*counting errors*/
        data _null_; 
            infile "&loglocation./&selected_log."  end=last;
            input;
            if _infile_  =: 'ERROR' then error_count+1;
            if last and error_count >=1 then CALL EXECUTE('%rerun(&selected_log. ,         &selected_code.)') ;
            if last and error_count < 1 then CALL EXECUTE('%no_rerun(&selected_log.)') ;
        run;


    %end;



%mend;


%macro rerun(log,code);


    %let syscc = 0;
    %include "&codelocation./&code." ;

    %if &syscc. <= 6 %then %do;
            %success(&log.);
        %end;

    %else %do;
            %failure(&log.)
        %end;

%mend;


...
    
%rerunner();
sas sas-macro
1个回答
0
投票

这里有一个时间问题。您的宏

%rerun
正在使用在发生任何事情之前定义的 &syscc!

思考这个问题的方法是将其视为有 2 个通道。首先是“宏观”通道,然后是“SAS”通道。

  • 宏传递:执行所有宏语言操作(主要以 % 开头的操作),并创建更大的 SAS 代码
  • SAS pass:作为 SAS 代码运行

所以 %rerun 像这样工作。

起始代码:

%macro rerun(log,code);    
    %let syscc = 0;
    %include "&codelocation./&code." ;
    %if &syscc. <= 6 %then %do;
            %success(&log.);
        %end;
    %else %do;
            %failure(&log.)
        %end;
%mend;

宏展开步骤:

%let syscc=0;

-- syscc=0

%include "&codelocation./&code.";

-- 将该位置的代码包含到 SAS 代码中(但不运行它)

%if &syscc <= 6 %then %do;
     %success(&log.);
%end;

-- syscc=0,所以小于六,所以做这部分 -- 将宏成功展开到 SAS 代码中并将其包含在此处

%else %do;
%end;

——这没有任何作用,因为 if 是 true

现在,

%rerun
宏进入 SAS 代码步骤,并实际执行操作。除了...代码是否设置错误并不重要,因为不再在任何地方检查 syscc - 它已经通过
syscc=0
路径。

如果你想做这样的事情,你需要有一种方法在宏执行期间交互式地查找syscc的值。这是可能的,但这不是最好的设计。

这里更好的设计是在宏(或其他)执行结束时将 &syscc 的值存储到数据集中,并检查 that,可能会从中调用重新运行。

data syscc_status;
input prog $ timestamp :datetime17. syscc;
datalines;
prog1 01JAN2024:01:01:01 3
prog2 01JAN2024:01:01:02 8
prog3 01JAN2024:01:01:03 6
;;;;
run;

类似这样的事情。然后你的程序运行时可以像这样在包装器中:

%macro runprogram(program=,log=);
  %let syscc=0;
  proc printto log="&log";
  run;
  %include "&program";
  proc printto;
  run;

  data syscc_append;
    prog="&program";
    timestamp = now();
    syscc=&syscc;
  run;

  proc append base=syscc_status data=syscc_append;
  run;
%mend runprogram;

现在你可以做这样的事情:

proc sql;
  select cats('%rerun(program=',prog,')') into :proglist separated by ' '
   from syscc_status
    where timestamp gt dhms(today(),0,0,0)
  ;
quit;

&proglist;

并且您的

%rerun
宏只是调用 runprogram 宏(它可能只是直接调用 runprogram 宏,除非您想做其他事情)。显然,如果不简单,您可能还需要发送日志名称。

© www.soinside.com 2019 - 2024. All rights reserved.