专栏首页SAS程序分享号号号SAS-走近Log,实现程序的“风险控制”

SAS-走近Log,实现程序的“风险控制”

从第一天学习SAS开始,就摆脱不了看SAS日志,每次运行完程序的第一件事,不是看程序运行的结果,而是点击一下Log页面,第二件事也不是去看结果,而是仔细的浏览Log里面,有没有红色的字体出现(ERROR),有没有绿色的字体出现(WARNING),接着在看有没有黑色的_ERROR_=1出现(出现这种情况,一般是你的数据不满足条件或者语法有问题,下面会有例子),接着还得再看看有没有蓝色的字体(XXX未初始化)出现。就目前小编主要看的也就这四种常见的问题。肯定是不全的,各位大神如有兴趣可以留言补充~

1 概述日志作用

1、检查语法

日志最重要的一个作用就是在运行程序的时候,检查你的语法是否有问题。以目前小编常见的Log报出的错误分为几类。

ERROR

ERROR:在log中是以红色的字体存在,有ERROR存在的程序,是会的结果造成一定影响的,一般都是存在语法的问题。(仅举一例,如下截图),同时我们也可以通过故意error,让Log来提示我们语法..

WARNING

WARNING:在Log中是以绿色的字体存在,有WARNING程序也是有点问题,有时候不太影响结果,不过这个得具体情况具体看,最理想的情况下是零ERROR零WARNING,当有WARNING存在的时候,还是应该Check一下你的程序,如果解释的过去,到也无所谓..纯属个人早期观点,小编现在对自己有要求了,尽量时Log达到理想状态。(下图,随便造了一条WARNING)

_ERROR_

注意此处的_ERROR_非前面提到的ERROR,此处的_ERROR_是以黑色字体存在的,当出现这个的时候一定要注意一下程序,虽然程序结果不一定有问题,可能是数据或者其他的什么不满足你程序的要求,但是还是要在次check下程序。兴许真的是你程序写错了。顺便再一句相关的Option选项,在程序的开始可以加一个option error=1;的选项这样的话如果出现了黑色的error不会哗啦出现一大屏幕,没一类或者每一处error只在log上显示一次。这个是一个很好的option。(下面举个例子,将变量字符型转换成数值型(日期),采用input的方式,此次为数据问题,非程序问题,但是此处的黑色error是可以通过程序去避免产生的)。

蓝色的“NOTE”

看日志,除了上面有颜色的需要看,蓝色的也需要看,有一些蓝色的NOTE虽然不严重,但是还是需要以一个严谨的态度对待程序,哪些蓝色的需要注意呢,首当其冲当然是“XXX未初始化”、“函数xxx的参数无效”....针对未初始化的情况,可能提示你的变量名称写错了等等..是需要值得注意的,和消除未初始化在你Log中的存在。

期待您的补充

2、程序调试等提示

能通过上面的提示,我们就可以去找到你程序对应的位置,去修改程序,起到一个调试的作用,在如我们将一些信息Put到日志上去,辅助程序的编写,在如小编之前写过一篇SAS-Macro调试技巧的推送(可查看历史消息),里面就是利用一些options将Macro的执行可视化到日志上去。

3、当做证明

能check程序的语法,当然也能证明你程序语法没有问题(至于你程序的逻辑有无问题,这个只能靠你自己了),有时候你要证明你的程序没有问题,你说你没问题别人就信么,空口无凭啊,这个时候Log就派上用场了,那么问题来了。SAS中如何将Log导出?

2 俩种最常见方式导出Log

01 proc printto法

/*此处将log输出*/
proc printto log = "D:\日常练习\sas_checklog\test1.log" new; run;
/*恢复到SAS里面的日志*/
proc printto; run;

如上,将Log输出,然后又恢复到SAS系统里面的Log,这个方法呢,这个呢,需要你把你运行的程序放到他们中间。

02 dm replace法

dm 'log; log; file "D:\日常练习\sas_checklog\TEST1.log" replace ;'; run;

这个看起来很简单,俩种方式都各有优势,好像是前一种不会出现Log打印满的了情况,后一种则是先输出在SAS系统里面,然后在输出,在SAS里面Log行的是有限制的。当然一般正常的程序这个我们都用到上限的行。在补充一句,这个纯属个人对SAS的理解,未经证实,小编也懒得百度去证实一下真伪。如果是假的,记得留言告诉我一声哎~

03 书到用时方恨少

这个不是方法...是我要请教各位真神的一个问题,我想利用SAS语言(非手动方式点点点)将Log输出成pdf,并保留其Log中的颜色,请问可以做到么?该如何做到?我百度了良久,未找到解决方案,深感书到用时方恨少..

3 如何快捷的Check日志

导出日志不是我们最终的目标,导出了日志如何快速的找出你日志中存在的问题,最后形成一个report与日志与程序与结果一起保存下来,或者提交给你对接的人。才是我们最终的目的,这个应用一句从别人那里“借”来的话:“风险控制”,此处的风险指的是程序的风险。

如何快捷的从log中提取关键信息(error,warning等),并输出成报告,这个可以用Macro去实现,这个Macro怎么写呢,接下来就与我一起来写一下这个简单的Macro~

会用到的一些知识点

在贴代码前,私以为还是先简单提一下会用到的语法或者知识点,有兴趣的朋友可以着重找你想知道的~一个很简单Macro,这回被我写的感觉好复杂啊

1、正则表达式的运用

此处对正则的使用,是拆分输入的路径。如 E:\L\M\ yy.txt 此时可以得到E:\L\M

2、filename pipe的运用

此处是自动获取路径下的文件名及路径,关于pipe的使用,小编有一点需要提示:其原理是SAS与DOS的交互,因此你的路径夹路径中不能有空格,有空格就有点问题哎。暂时小编还不知道怎么解决此问题,因此小编的文件夹命名,都不在添加空格。

3、Check宏变量的几个函数的使用

此函数是检查你的宏变量(局部宏变量)是否定义。SAS中一个有3个函数Check 宏变量是否定义。如下(借用官网的几个实例)

4、call execute的使用

其功能就是执行语句,其实这里可以写很多的这种执行语句,不过小编还是用的不是很习惯,其实不能说是用的不习惯,因为用的过程中遇到了一点问题,暂时还没解决,因为觉得是execute语法的有点限制,不细说了,因为我也不太清楚,这个就涉及到data运行数据的原理了..。

5、定义Macro变量的方式

sql 与symput

写代码前,先看结果

首页:(第一个sheet的汇总)

后面的sheet是Log详情:小编将每个(ERROR,的前俩条与后俩条记录同时输出):

此处Macro 分为俩部分:%chk_log_ds:辅助性Macro,%chk_Log:功能性Macro

%macro chk_log_ds(ds,loop);
/*使用infile 导入数据*/
data &ds._1;
length type $100.;
infile fn&loop. end=last;
input desc $1-5000 @@;
line=_N_;
if index(desc,"_ERROR_")  then type="B_ERROR_";/*_ERROR_在数据操作中会有点问题,暂且在前面加一个字符后续会转化回去*/
else if index(desc,"ERROR") then type="ERROR";
else if index(desc,"WARNING") then type="WARNING";
else if index(desc,"未初始化") or index(desc,"uninitialized") then type="UNINITIALIZED";
run;
/*获取每个类型ERROR的前俩行与后俩行(便于详情列表中的review)*/
data log_tmp;
set &ds._1;
if ^missing(type) then do;
a1=line-2;
a2=line-1;
a3=line;
a4=line+1;
a5=line+2;end;
where ^missing(type);
keep LINE  type a1-a5;
run;
%let dsid=%sysfunc(open(log_tmp));
%let _nobs=%sysfunc(attrn(&dsid,nobs));
%let rc= %sysfunc(close(&dsid));
%if &_nobs. eq 0 %then %do;
data &ds._desc;
length LogName $200.;
LogName="&ds.";
ERROR=0;
_ERROR_=0;
WARNING=0;
UNINITIALIZED=0;
run; 
%end;
%if &_nobs. ne 0 %then %do;
proc freq data=LOG_tmp noprint; 
 table  type/   out=&ds._desc1(keep=type COUNT );
run;
proc sort data=&ds._desc1  out=&ds._desc1 ;by type ;quit;
proc transpose data=&ds._desc1 out=&ds._desc  ;
var COUNT;
ID type;
IDLABEL type;
run;
data &ds._desc;
set &ds._desc;
length LogName $200.;
LogName="&ds.";
DROP _NAME_ _LABEL_;
run;
proc sort data=log_tmp(drop= type)  out=log_tmp_  ;by LINE ;quit;
proc transpose data=log_tmp_ out=log_tmp_  prefix=ORRES;
by LINE;
var a1-a5;
run;
proc sql noprint;
select ORRES1 into:varlist separated by ' '  from log_tmp_   ;
quit;
data &ds.;
set &ds._1 ;
if type="B_ERROR_" then Type="_ERROR_";/*转化回本身*/
where line in (&varlist.);
run;
proc delete data=LOG_tmp LOG_tmp_  &ds._1 &ds._desc1 ;quit;
%end;
%mend;
%macro chk_log_mn(path=,encoding=gb2312);
/**********************************************************
check是单个log的核查,还是多个log的和核查
原理是:当path填写了具体的文件名称(以txt 或者 Log后缀的文件名称)
当path为一个文件路径时,自动扫描获取文件路径下的txt/Log文件。
并以log名称为数据集名称在给log取名时需要注意.
***********************************************************/
%put NOTE:&path.;
%let file=%sysfunc(PRXCHANGE(s/(.*)\\.*/\1/,-1,&path));
%put NOTE:&file.;
%if %upcase(%qscan(%qscan(&path,-1,'\'),-1,'.'))=TXT  or %upcase(%qscan(%qscan(&path,-1,'\'),-1,'.'))=LOG  %then %do;
%let _mian=%scan(&path,-1,'\');
%put NOTE:&_mian.;
%end;
/**********************************************************
利用Pipe或缺文件夹下文件列表
***********************************************************/
filename xcl_fil pipe "dir &file\*.*/b/s"; 
data _templog;
infile xcl_fil truncover;
input fname $char1000.;
put fname=;
dsn=scan(scan(fname,-1,'\'),1,'.');
/**********************************************************
用symlocal函数检查是否创建了_Main宏变量
如果创建则返回1,没有创建则返回0
/************************************************************/
%if %symlocal(_mian)=1 %then %do;
if find(upcase(fname),upcase("&_mian."))>0  then output;
%end;
%else %if %symlocal(_mian)=0 %then %do;
if find(upcase(fname),'.TXT')>0 or find(upcase(fname),'.LOG')>0   then output;
%end;
;
run;
data _templog2;
length data1 $20000.;
set _templog;
/**********************************************************
创建一个filename 利用filename
利用call execute 执行语句
利用复制性Macro实现对Log数据集的加工/筛选
***********************************************************/
call execute("filename "||strip(compress("fn"||_N_))||'  "'||strip(fname)||strip('"  encoding=')||left("&encoding.;"));
call symput('N'||compress(put(_n_,best.)),strip(dsn));
run;
%let dsid=%sysfunc(open(_templog2));
%let nobs=%sysfunc(attrn(&dsid,nobs));
%let rc= %sysfunc(close(&dsid));
%do j=1 %to &nobs;
%chk_log_ds(&&N&j.,&j.)
%end;
data contents;
retain LogName;
set %do i=1 %to &nobs.;%sysfunc(compress(&&N&i.._desc))  %end;;
if missing(B_ERROR_) then B_ERROR_=0;
if missing(ERROR) then ERROR=0;
if missing(WARNING) then WARNING=0;
if missing(UNINITIALIZED) then UNINITIALIZED=0;
run;
data _lasttemp;
set contents;
where sum(B_ERROR_,ERROR,WARNING,UNINITIALIZED)^=0;
call symput('M'||compress(put(_n_,best.)),strip(LogName));
run;
%let dsid=%sysfunc(open(_lasttemp));
%let _mloop=%sysfunc(attrn(&dsid,nobs));
%let rc= %sysfunc(close(&dsid));
/**********************************************************
输出过程
***********************************************************/;
ods path tpt.template(read)  sasuser.templat(read) sashelp.tmplmst(read);
ods listing close;
ods RESULTS off;
ods escapechar='^';
ods excel file="&file.\ Log report.xlsx" options(contents="no"  FROZEN_HEADERS="Yes" autofilter='all' ) style=tag_1;
ods excel options(embedded_titles='no' embedded_footnotes='no');
%let ps1=800;
%let ls1=256;
Options ps=&ps1 ls=&ls1  nodate nonumber nocenter;
OPTIONS FORMCHAR="|----|+|---+=|-/\<>*"; 
ods excel options(sheet_name="Contents_Index"  START_AT='D4') ;
proc report data=contents  headskip headline nowd  
style(header)={just=c asis=on font_weight=bold font_style=italic} ;
column ("Contents of Table" LogName ERROR B_ERROR_ WARNING UNINITIALIZED);
define LogName/ computed display style=[ just=left tagattr='text'  cellwidth=15% ] ;
define ERROR/ display "ERROR" style=[ just=left tagattr='text' cellwidth=15% ] ;
define B_ERROR_/  display "^__ERROR_"  style=[ just=left tagattr='text' cellwidth=15% ];
define WARNING/ display style=[ just=left tagattr='text' cellwidth=15%] ;
define UNINITIALIZED/ display style=[ just=left tagattr='text' cellwidth=15%] ;
compute LogName ;
if LogName ne '' and  sum(B_ERROR_,ERROR,WARNING,UNINITIALIZED) ne 0  then do;
urlstring = "#" ||strip(LogName)|| "!A1";
call define(_col_, 'URL', urlstring);
end;
endcomp;
run;
ods excel options(START_AT='A1' ) ;
%do mlop=1 %to &_mloop.;
ods excel options(sheet_name="&&M&mlop" ) ;
proc report data=&&M&mlop.   headskip headline nowd   contents="Contents_Index." ;
column ("日志详情" _ALL_);
define line /  display style=[ just=left tagattr='text'  cellwidth=4% ] ;
define type / computed display style=[ just=left tagattr='text'  cellwidth=15% ] ;
define desc /  display  "Description" style=[ just=left tagattr='text'  cellwidth=80% ] ;
compute type ;
if type  eq "ERROR"  then do;
call define(_ROW_,"style","style={  foreground=RED  }"); 
end;
if type  eq "_ERROR_"  then do;
call define(_ROW_,"style","style={  foreground=black }"); 
end;
if type  eq "WARNING"  then do;
call define(_ROW_,"style","style={  foreground=Green }"); 
end;
if type  eq "UNINITIALIZED"  then do;
call define(_ROW_,"style","style={  foreground=Blue  }"); 
end;
endcomp;
run;
%end;
proc delete data=work._lasttemp   _templog _templog2 ;quit;
ods excel close;
ods  listing;
%mend;
%chk_log_mn(path=D:\日常练习\sas_checklog\);
%chk_log_mn(path=D:\日常练习\sas_checklog\test.log);
文章分享自微信公众号:
SAS程序分享号号号

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!

如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • SAS-编程中的小技巧(七)

    虽然难以启齿,但是花费巨额的代价买的教训,还是想分享给大家。“驾驶有风险,开车需谨慎”

    Setup
  • 【资讯】专访SAS高管:Value是大数据的精髓

    image.png ▲Sas公司大数据研究与发展全球副总裁Paul Kent 专注数据分析近40年的SAS公司,在大数据时代更加如鱼得水。20...

    小莹莹
  • 【学习】Think SAS(二)

    第一篇“Think Sas”中的“Think”,纯粹做“考虑”解,说,诸君如果为工作计,不妨考虑下SAS。下面说些关于SAS本身的一些思考与认识...

    小莹莹
  • NVIDIA Jetson边缘设备助力台北荣总医院洗肾中心打开“精准医疗”大门

    随着医疗行业的飞速发展,如何能针对每位患者的病情和个体差异,快速、精确地选择适合的诊疗方案,成为了人们关注的新焦点。在临床实践中,如何最大化病患问诊效率和利益,...

    GPUS Lady
  • SAS-异常报表邮件自动预警

    当前在用报表平台是帆软旗下的BI和Report,目前版本还不支持邮件提醒异常报表。

    崔洞洞
  • 拉夏贝尔财报:“中国版ZARA”出局

    “全力以赴争取实现2020年度扭亏为盈的目标。”6月29日,拉夏贝尔在姗姗来迟的2019年年度财务报告中如此表示。

    刘旷
  • 临床试验统计篇-肿瘤试验终点指标计算

    临床试验终点(End Point)服务于不同的研究目的。在传统的肿瘤药物的研发中,早期的临床试验目的是评价安全性以及药物的生物活性,如肿瘤缩小。后期的有效性研究...

    臭脚妹妹
  • SAS-Macro 中的那些语句(二)

    昨天哪一篇说了宏变量定义的三种方式(SAS-Macro 中的那些语句(一)),今天接着昨天的说...还是围绕着宏变量进行展开,第一个问题,宏变量的作用域有限制么...

    Setup
  • 谈资 | 十日大数据参考

    我们将过去10天里播报的大数据新闻,浓缩成17条精选资讯,您只要在20分钟就可以读完,了解下这个行业的变化吧~ 1. 数说× “各行各业都在装备大数据” 2....

    数说君
  • DELL存储SCv2000/2020基础配置与使用

    描述: 最近业务需要需要将原本装有VMware vSphere的机器直接安装Ubuntu 20.04 TLS,并通过SAS线缆从DELL Storage SCv...

    WeiyiGeek
  • 「企业安全架构」EA874:安全架构团队

    业务要求安全架构师(SA)提供安全的解决方案和服务,这些解决方案和服务可以安全地支持诸如增加利润和生产力、改进客户服务、创新以及更快地将新产品和服务推向市场等活...

    首席架构师智库
  • 一家商业数据分析公司SAS,如何保持了40年的持续增长?

    ? SAS公司联合创始人兼CEO Jim Goodnight SAS公司成立40年来一直保持增长态势,名字却很朴实,SAS即Statistical Analy...

    灯塔大数据
  • 大数据周周看 | 数据专家“跳槽”成“风”为圆创业梦 蓝色光标发布大数据产品“词云”

    上周,去哪儿网宣布成立营销中心,借大数据打造“智慧旅游”服务;蓝色光标发布大数据新品“词云”,可提供内容可视化洞察;前SAS中国研发中心高管曹新建加盟索信达,负...

    数据猿
  • 专注分析40年,SAS如何看待数据 | 直击SAS 2018全球论坛

    大数据文摘
  • SAS学习笔记之《SAS编程与数据挖掘商业案例》(2)数据获取与数据集操作

    版权声明:本文为王小雷原创文章,未经博主允许不得转载 https://blog.csdn.n...

    王小雷
  • 大数据,银行风险管理的金钥匙

    大数据文摘
  • 【SAS Says】基础篇:6. 开发数据(二)

    如果你管着一份10000条的客户数据,有一天,老板拿着一个500人的表告诉你,这表上的500位客户的信息发生了变动,而且变动的变量很不规律,如客户102是收入发...

    数说君
  • 干货 | 携程基于大数据分析的实时风控体系

    携程技术
  • 混合云安全的5个关键策略

    静一

扫码关注云+社区

领取腾讯云代金券