Question

I'm trying to figure out how to use SAS namedpipes to exchange data in SAS processes. Here is a simple example:

Server

FILENAME stdout namepipe '\\.\pipe\Sas\PipeOut' server eofconnect retry=15 block;
FILENAME DIRLIST pipe 'dir "C:\atemp"';
data dirlist ;
    length buffer $256;
    infile dirlist length=reclen;
    input buffer $varying256. reclen;
    *file stdout;
    *put buffer;
ods listing file=stdout;
proc print data=dirlist;
run;

Client

FILENAME stdin  namepipe '\\.\pipe\Sas\PipeOut'  client eofconnect retry=15 block;
data d1;
    length buffer $ 256;
    infile stdin length=reclen;
    input buffer $varying256. reclen;
    put buffer;
run;

If in the server code I uncomment out the file and put statement and remove the ods and proc print, everything pretty much works as expected. The code as it stands produces results I didn't expect. I run the server code, then start the client code. The client code runs but reads zero observations, if I then rerun the client code (before the server times out) it will then read the 60 or so expected lines, then hangs (never terminates). My best guess is that the ods listing statement closes the file, then reopens it (and never closes it?). Does anyone know what's going on and how to get the ods output in the client on the first execution, with no hang?

Something else I'd like to do is output the data set on the server to the pipe and using it as a dataset reference in client. Generally this is done using a library reference and I don't know if or how I can make the pipe file reference appear to be a library reference. Hope that last part makes sense.

Was it helpful?

Solution

First, to fix the hanging, you need to close the pipe on the server.

ods listing close;

I cannot explain having to run the client twice.

Changing the code to this works.

Server

FILENAME stdout namepipe '\\.\pipe\Sas\PipeOut' server eofconnect retry=15 block;
FILENAME DIRLIST pipe 'dir "C:\temp"';
data dirlist ;
    length buffer $256;
    infile dirlist length=reclen;
    input buffer $varying256. reclen;
    *file stdout;
    *put buffer;
run;

ods listing file=stdout;

proc print data=dirlist;
run;

ods listing close;

Client

FILENAME stdin  namepipe '\\.\pipe\Sas\PipeOut'  client retry=15 ;

 /*Extra read to clear whatever weirdness ODS does.*/   
data _null_;
infile stdin;
input;
run;

data d1;
    length buffer $ 256;
    infile stdin length=reclen;
    input buffer $varying256. reclen;
    put buffer;
run;

I suspect, that the ODS statement does something to create a the file. This is a first write to the pipe. The next write to the pipe is a modification. That's why you have to read from it twice.

For your second question about sharing data. I am not sure you can pipe the dataset in binary form. You could write it as something like CSV to the pipe and read it into a data set on the client.

Server

FILENAME stdout namepipe '\\.\pipe\Sas\PipeOut' server eofconnect retry=15 block;

proc export data=sashelp.class outfile=stdout dbms=csv replace;
run;

filename stdout clear;

On the client you need to write the results to a temporary file. Proc IMPORT needs random access and a named pipe cannot be accessed randomly.

FILENAME stdin  namepipe '\\.\pipe\Sas\PipeOut'  client retry=15 ;

filename x temp;
data _null_;
    length buffer $4000.;
    infile stdin length=reclen;
    file x;
    input;
    buffer = _infile_;
    put buffer;
run;

proc import file=x out=class dbms=csv replace;
run;

filename x clear;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top