2011-11-22 14 views
5

Voglio chiamare un programma SAS da un altro programma su Windows. Ho un po 'di esperienza nell'invocare SAS dalla riga di comando in modalità batch, ma nessuna esperienza reale nella ricezione di messaggi da esso e nella gestione di tali messaggi. Ho cercato su Google e ho trovato un bel po 'di informazioni sulla lettura da stdin da un programma SAS, ma non riesco a capire come rendere il mio programma SAS scrivere su stdout o stderr. Posso farlo anche su Windows?Cattura stdout e stderr da SAS in Windows?

Dal programma SAS, vorrei fare quanto segue:

  • reindirizzamento messaggi di avviso e messaggi di errore a stderr invece di stampare il file di registro
  • Nell'ambito del programma SAS, manualmente rilevare gli errori e/o altri problemi e inviarli a stderr o stdout.

Ecco che cosa ho provato:

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 che chiama la 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() 

I miei risultati sulla console da questo sono:

('', '') 
+1

Non ho mai usato SAS, ma è un'app per console? Potrebbe non avere maniglie per stdout/stderr. In tal caso, prova il modulo 'win32com' di PyWin32 su [automatizza SAS usando OLE] (http://support.sas.com/documentation/cdl/en/hostwin/63285/HTML/default/viewer.htm#oleauto.htm). – eryksun

+0

Ecco un collegamento alla documentazione SAS sull'utilizzo di pipe senza nome che potrebbero essere utili: http://support.sas.com/documentation/cdl/en/hostwin/63285/HTML/default/viewer.htm#unnamed.htm – RWill

risposta

2

per quanto so che questo non è possibile ottenere direttamente. È possibile emulare questo passando un nome file univoco in sas utilizzando il parametro -sysparm della riga di comando e salvando l'output STDOUT su quello. È quindi possibile utilizzare il parametro della riga di comando -log per inviare il registro sas a un file diverso. Una volta terminato il programma SAS, sarà possibile utilizzare il programma scelto per analizzare ciascuno dei file prodotti. Sfortunatamente il file di registro è bloccato fino al termine del programma sas, quindi se si desidera utilizzare SAS per elaborare il file di log, è necessario avviare un programma secondario di follow-up per farlo. (ad esempio non è possibile leggere il file di registro dal programma SAS che lo sta creando).

Una volta letto il log in è possibile cercare le righe che iniziano con ERROR: o WARNING: e intraprendere le azioni appropriate (nel mio caso invia un'email a me). Potresti aggiungere una logica adatta al tuo stile di codifica. Ad esempio, alcune cose che SAS considera NOTES, considero gli ERRORI. Inoltre, alcune cose di SAS sono ERRORI a cui non mi importa. Ecco la logica che uso:

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; 

Spero che questo aiuti.

+0

Solo un pensiero - usando le prese si potrebbe ottenere SAS per emulare l'invio a STDOUT.Il vecchio modulo SAS/Intranet funzionerebbe anche a questo scopo .... –

+0

Grazie Rob. Ho usato il sysparm e il registro argomenti del file per l'elaborazione in batch prima, quindi penso che andrò per questo approccio. Peccato per il file di registro bloccato. Spero di avere abbastanza controllo sui dati di input per evitare molti degli errori che avrei dovuto analizzare, quindi forse Sono in grado di rilevare il maggior numero di osservazioni possibile (ad esempio un numero diverso di osservazioni del previsto) ed emettere il mio STDERR emulato. Inoltre, cercherò le prese. – oob

2

Non ho una versione di Windows di SAS a portata di mano, ma su UNIX ho reindirizzare a STDOUT come questo:

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

Non sei sicuro di come reindirizzare il log degli errori per STDERR, ma la stampa su STDERR sarebbe simile a questa :

ods listing file=STDERR; 

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

interessante . Questo non funziona su Windows. Immagino che SAS non abbia le maniglie stdout/stderr :( – oob

+0

'file list ods = STDERR;' funziona su unix. Grazie –

-1

Googled reindirizzando il registro per STDERR per voi:

proc printto log=STDERR; 
    run; 

    data _null_; 
     1=x; 
    run; 
+0

Grazie, ho provato questo. Non reindirizza il log a stderr. Crea un file di log chiamato 'stderr.log'. – oob

Problemi correlati