我想从Windows上的其他程序调用SAS程序。我有一些在批处理模式下从命令行调用SAS的经验,但没有真正的经验从它接收消息并处理这些消息。我已经google了一下,发现了很多关于从SAS程序中读取stdin的信息,但我似乎无法弄清楚如何让我的SAS程序写出到stdout或stderr。我甚至可以在Windows中执行此操作吗?
从SAS计划,我想做以下事情:
以下是我的尝试:
SAS
data test;
attrib i length=8;
do i = 1 to 10;
put 'putting'; *how can i make this go to stdout?;
putlog 'putting to log'; *this can go to the log - that is okay;
if i = 5 then do;
*pretend this is an error I am manually detecting - how can i make this go to stderr?;
put 'we found 5';
end;
output;
end;
run;
data _null_;
1 = y; *this is an error detected by SAS. How can I make this go to stderr?;
run;
调用SAS的Python:
import subprocess
import os
if __name__ == '__main__':
filename = os.path.normpath(r'C:\Users\oob\Desktop\sas_python_test.sas')
sas_executable = os.path.normpath(r'C:\Program Files\SAS\SASFoundation\9.2\sas.exe')
cmd = r'"' + sas_executable + r'"' + " " + r'"' + filename + r'"'
p = subprocess.Popen(cmd,shell=False,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
print p.communicate()
我在控制台上的结果是:
('', '')
答案 0 :(得分:2)
我没有Windows的Windows版本,但在UNIX上我会像这样重定向到STDOUT:
data _null_;
file STDOUT;
do i=1 to 10;
put i=;
end;
run;
不确定如何将错误日志重定向到STDERR,但打印到STDERR将如下所示:
ods listing file=STDERR;
proc print data=sashelp.class;
run;
答案 1 :(得分:2)
据我所知,这是不可能直接实现的。您可以通过使用-sysparm命令行参数将唯一文件名传递给sas并将STDOUT输出保存到该模板来模拟此操作。然后,您可以使用-log命令行参数将sas日志发送到其他文件。 SAS程序完成后,您将能够使用您选择的程序来解析生成的每个文件。不幸的是,日志文件被锁定,直到sas程序完成它,所以如果你想使用SAS来处理日志文件,你需要启动一个二级跟进程序来执行此操作。 (即,您无法从创建它的SAS程序中读取日志文件。)
阅读完登录后,您可以查找以ERROR:或WARNING开头的行:并采取相应的操作(在我的情况下,它会向我发送电子邮件)。您可能希望添加一些适合您的编码风格的逻辑。例如,SAS将某些东西视为NOTES我认为是错误的。此外,SAS认为有些东西是我不关心的错误。这是我使用的逻辑:
data problems log;
length line $1000;
infile "&logfile";
input;
logfile = "&logfile";
line_no = _n_;
line = _infile_;
problem = 0;
if
(
line =: "ERROR:"
or line =: "WARNING:"
or line =: "NOTE: Numeric values have been converted to character values"
or line =: "NOTE: Character values have been converted to numeric values"
or line =: "NOTE: Missing values were generated as a result of performing an operation on missing values"
or line =: "NOTE: MERGE statement has more than one data set with repeats of BY values"
or line =: "NOTE: Invalid (or missing) arguments to the INTNX function have caused the function to return"
or line =: "INFO: Character variables have defaulted to a length of 200"
or line =: "NOTE: Invalid"
)
and not
(
line =: "WARNING: Your system is scheduled to expire"
or line =: "WARNING: The Base Product product with which Session Manager is associated"
or line =: "WARNING: will be expiring soon, and is currently in warning mode to indicate"
or line =: "WARNING: this upcoming expiration. Please run PROC SETINIT to obtain more"
or line =: "WARNING: information on your warning period."
or line =: "WARNING: This CREATE TABLE statement recursively references the target table. A consequence"
or line =: "WARNING: Unable to copy SASUSER registry to WORK registry. Because of this, you will not see registry customizations during this"
or line =: "WARNING: Estimates did not improve after a ridge was encountered in the objective function."
or line =: "WARNING: Estimates may not have converged."
or line =: "ERROR: A lock is not available for"
or line =: "ERROR: Errors printed on pages"
)
then do;
problem = 1;
output problems;
end;
output log;
run;
希望这有帮助。
答案 2 :(得分:-1)
用Google搜索将日志重定向到STDERR:
proc printto log=STDERR;
run;
data _null_;
1=x;
run;