Использование namedpipes для передачи вывода ods и наборов данных

Я пытаюсь понять, как использовать именованные каналы SAS для обмена данными в процессах SAS. Вот простой пример:

сервер

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;

клиент

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;

Если в коде сервера я раскомментирую файл, добавлю оператор и удаляю ods и proc print, все в значительной степени работает, как и ожидалось. Код в его нынешнем виде дает результаты, которых я не ожидал. Я запускаю код сервера, затем запускаю код клиента. Клиентский код выполняется, но читает нулевые наблюдения, если я затем повторно запустил клиентский код (до истечения времени ожидания сервера), он затем прочитает 60 или около того ожидаемых строк, а затем зависнет (никогда не завершится). Мое лучшее предположение заключается в том, что оператор ods list закрывает файл, а затем снова открывает его (и никогда не закрывает его?). Кто-нибудь знает, что происходит и как получить вывод ods в клиенте при первом запуске, без зависаний?

Что-то еще, что я хотел бы сделать, это вывести набор данных на сервере в канал и использовать его как ссылку на набор данных в клиенте. Обычно это делается с помощью ссылки на библиотеку, и я не знаю, могу ли я или как сделать, чтобы ссылка на файл канала представлялась ссылкой на библиотеку. Надеюсь, что последняя часть имеет смысл.

1 ответ

Решение

Во-первых, чтобы исправить зависание, необходимо закрыть канал на сервере.

ods listing close;

Я не могу объяснить необходимость запуска клиента дважды.

Изменение кода на это работает.

сервер

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;

клиент

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;

Я подозреваю, что оператор ODS делает что-то для создания файла. Это первая запись в трубу. Следующая запись в трубу - это модификация. Вот почему вы должны читать из него дважды.

На ваш второй вопрос об обмене данными. Я не уверен, что вы можете передать набор данных в двоичном виде. Вы можете записать это как что-то вроде CSV в канал и прочитать его в набор данных на клиенте.

сервер

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;

На клиенте вам нужно записать результаты во временный файл. Proc IMPORT требуется произвольный доступ, а именованный канал не может быть доступен произвольно.

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;
Другие вопросы по тегам