Monday, July 8, 2013

Turn off ERRORABEND for an optional, potentially unstable part of a SAS program

Usually I want my production SAS processes to terminate immediately when they encounter an unhandled error.  This is to prevent corrupting existing data structures with bad updates and the like.  To this end, I set  the ERRORABEND option at the beginning of these programs since it will abend/terminate a program when an error occurs.

Some of my programs %INCLUDE code downloaded from a live FTP site.  I always want the latest code or I could cache a local copy.  Unfortunately the FTP site is sometimes unexpectedly down for maintenance when my program calls out to it and causes an error.  Given that I have ERRORABEND set, this crashes the program run before it even really gets going.  I decided that the FTP-related code is not absolutely essential for a successful program run, so I needed a way to keep going through the rest of the program even if the FTP part fails.

The approach I've taken to "ignore" an FTP-related error is to set the NOERRORABEND system option right before the FTP download and then set it back to ERRORABEND (or whatever it was set to) right after the FTP code gets executed.

The key part is the DICTIONARY.OPTIONS table that stores current option settings.  You can think of this table as storing a list of key-value pairs, with the key being the option name and the value being the option's current setting.  The key variable is called OPTNAME and the value variable is called SETTING.

Here's a sample of what you might find in the table.

proc sql;
    select optname, setting 
    from dictionary.options 
    where upcase(optname) like 'ER%';
quit;

Option Name         Option Setting
--------------------------------------
ERRORABEND          NOERRORABEND
ERRORBYABEND        NOERRORBYABEND
ERRORCHECK          NORMAL
ERRORS              20

From this, you can tell my current setting for ERRORABEND is NOERRORABEND.

The unstable FTP handling code uses this information and executes the following steps: (1) grab the current value of the ERRORABEND option from DICTIONARY.OPTIONS, (2) stash the value in a macro variable for later use, (3) set the NOERRORABEND option, (4) run the FTP-related code, and (5) revert back to whatever (NO)ERRORABEND setting was in force before (the value stored in the macro variable during step 1).  Here is the code.

*Capture current ERRORABEND setting in a macro var;
proc sql noprint;
    select setting into :errorabend_setting 
    from dictionary.options 
    where upcase(optname)='ERRORABEND'; 
quit;

*Turn off errorabend with NOERRORABEND setting;
options NOERRORABEND; 

*Download and run the code file hosted on FTP;
filename runme ftp "file_to_download.sas"
         host  = "made_up_domain_name.org"
         cd    = "/formatcode"
         pass  = "secret"
         user  = "myloginname";
%include runme;

*Return errorabend setting to what it was prior to the FTP steps;
options &errorabend_setting;

A google search for "%opt2mvar" illustrates how this functionality can be packaged up in to a reusable macro.

1 comment:

  1. There's no need for SQL (or %opt2mvar-macro) to get the setting of an option:

    %let errorabend_setting = %sysfunc(getoption(ERRORABEND));

    ReplyDelete