在Windows中从SAS捕获stdout和stderr?

时间:2011-11-22 22:47:16

标签: python sas

我想从Windows上的其他程序调用SAS程序。我有一些在批处理模式下从命令行调用SAS的经验,但没有真正的经验从它接收消息并处理这些消息。我已经google了一下,发现了很多关于从SAS程序中读取stdin的信息,但我似乎无法弄清楚如何让我的SAS程序写出到stdout或stderr。我甚至可以在Windows中执行此操作吗?

从SAS计划,我想做以下事情:

  • 将警告消息和错误消息重定向到stderr,而不是将其打印到日志文件
  • 在SAS程序中,手动检测错误和/或其他问题,并将它们输出到stderr或stdout。

以下是我的尝试:

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()

我在控制台上的结果是:

('', '')

3 个答案:

答案 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;