2011-11-22 26 views
5

Quiero llamar a un programa SAS desde otro programa en Windows. Tengo cierta experiencia invocando a SAS desde la línea de comandos en el modo por lotes, pero no tengo experiencia en recibir mensajes y manejar esos mensajes. Busqué en Google y encontré bastante información acerca de cómo leer desde stdin desde un programa SAS, pero parece que no puedo entender cómo hacer que mi programa SAS escriba en stdout o stderr. ¿Puedo hacer esto en Windows?Capture stdout y stderr de SAS en Windows?

Desde el programa SAS, me gustaría hacer lo siguiente:

  • redirección de mensajes de advertencia y mensajes de error en stderr en lugar de imprimirlos en el fichero de registro
  • Dentro del programa SAS, manualmente detectar errores y/u otros problemas y enviarlos a stderr o stdout.

Esto es lo que he intentado:

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; 

Python que llama al SAS:

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

Mis resultados en la consola de esto son:

('', '') 
+1

Nunca he usado SAS, pero ¿es una aplicación de consola? Es posible que no tenga controladores para stdout/stderr. En ese caso, pruebe el módulo 'win32com' de PyWin32 para [automatizar SAS utilizando OLE] (http://support.sas.com/documentation/cdl/en/hostwin/63285/HTML/default/viewer.htm#oleauto.htm). – eryksun

+0

Aquí hay un enlace a la documentación de SAS sobre el uso de las tuberías sin nombre que pueden ser útiles: http://support.sas.com/documentation/cdl/en/hostwin/63285/HTML/default/viewer.htm#unnamed.htm – RWill

Respuesta

2

por lo que yo sé que esto no es posible alcanzar directamente. Puedes emular esto pasando un nombre de archivo único a sas usando el parámetro de línea de comando -sysparm y guardando tu salida STDOUT a eso. A continuación, puede utilizar el parámetro de línea de comandos -log para enviar el registro sas a un archivo diferente. Una vez que el programa SAS haya finalizado, podrá usar su programa de elección para analizar cada uno de los archivos que se produjeron. Lamentablemente, el archivo de registro está bloqueado hasta que el programa sas termina con él, por lo que si desea utilizar SAS para procesar el archivo de registro, deberá iniciar un segundo programa de seguimiento para hacerlo. (es decir, no puede leer el archivo de registro desde el programa SAS que lo está creando).

Una vez que haya leído el registro, puede buscar las líneas que comienzan con ERROR: o ADVERTENCIA: y tome las medidas adecuadas (en mi caso, me envía un correo electrónico). Es posible que desee agregar un poco de lógica que se adapte a su estilo de codificación. Por ejemplo, algunas cosas que SAS trata como NOTAS, las considero ERRORES. Además, algunas cosas que SAS trata como ERRORES no me importan. Esta es la lógica que utilizo:

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; 

Espero que esto ayude.

+0

Solo una idea: utilizando sockets, SAS podría emular el envío a STDOUT. El antiguo módulo de SAS/Intranet también funcionaría para este fin ... –

+0

Gracias Rob. He utilizado el sysparm y registro Archivo argumentos para el procesamiento por lotes antes, así que creo que voy a ir por este enfoque. Lástima que el archivo de registro esté bloqueado. Espero tener suficiente control sobre los datos de entrada para evitar muchos de los errores que tendría que analizar, así que tal vez Puedo detectar tantos como puedo (por ejemplo, diferentes observaciones de las que esperaba) y enviarlas a mi propio STDERR emulado. Además, buscaré en los sockets. – oob

2

que no tienen una versión para Windows de SAS útil, pero en UNIX vuelvo a dirigir a STDOUT como esto:

data _null_; 
    file STDOUT; 
    do i=1 to 10; 
    put i=; 
    end; 
run; 

No estoy seguro de cómo redirigir el registro de errores en STDERR, pero la impresión en STDERR sería el siguiente :

ods listing file=STDERR; 

proc print data=sashelp.class; 
run; 
+0

interesante . Esto no funciona en Windows. Supongo que SAS simplemente no tiene los identificadores stdout/stderr :( – oob

+0

'ods listing file = STDERR;' trabajar en Unix. Thanx –

-1

Googled redirigir el registro en STDERR para usted:

proc printto log=STDERR; 
    run; 

    data _null_; 
     1=x; 
    run; 
+0

Gracias He intentado esto. No redirige el registro a stderr. Crea un archivo de registro llamado 'stderr.log'. – oob

Cuestiones relacionadas