Использование 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;