2016-09-17 3 views
0

Я медленно становлюсь ближе, чтобы читать и писать в/из именованных каналов фонового процесса через SBCL. Что я делаю, это пнуть программу, которую я пытаюсь для чтения/записи из/в:Сложность чтения входной трубы в SBCL

[email protected]:~/CoreNLP$ cat ./spin | /usr/bin/java -cp "*" -Xmx2g edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,pos,lemma,ner,parse,dcoref -outputFormat text > ./spout & 

[1] 24616 

Так что все работает нормально, так что я пнуть SBCL и сделать это:

(defparameter from-corenlp (open "./spout")) 

Какие также отлично работает, но объявление потока приводит к тому, что SBCL проливает поток на экран (который является всей информацией о запуске из фонового процесса). Он не ждет, пока я не прочитаю из потока. Так ли это должно работать?

+0

* «Это как должно работать?» * Нет. Простой тест с «cat/dev/random> fifo» (fifo, сделанный с mkfifo) и открытие fifo из sbcl не позволяет мне копировать вопрос. Есть ли что-нибудь еще, что вы могли бы рассказать нам об этом? – coredump

+0

Хорошо, я подумал, что это не должно работать так. Я сделал тест, делающий кошку из файла, и результат оказался надежно на lisp-трубе. Объявление потока вывода из lisp в трубу: (defparameter to-corenlp (открыть «./spout»: direction: output: if-exists: append)) не работает. Никакие данные не поступали на принимающий конец в lisp, хотя я мог бы продолжать котировать входной файл в трубку для подачи, и данные будут поступать в поток lisp. –

+0

Интересно, что если я запускаю программу java, отправляющую вывод в трубу, программа по-прежнему не отправляет свои данные в трубу, однако ls> spout отправляет данные в трубу и может быть надежно прочитан в lisp. Для записи я попытался использовать sb-ext: run-program, и это не сработает. Любая java-программа с указанным аргументом (например, звездочка выше) вылетает, как только она запускается. Это не происходит с нижней оболочкой, но я понятия не имею, как получить функционирующий поток из lisp в порожденную программу одновременно с чтением из порожденной программы. –

ответ

2

Решение, как я отправил его в список парсер рассылки Стэнфорде (переполнение стека переформатировать много его на что-то странное, но вы получите идею):

Прошло довольно много времени, но я наконец-то понял, (по большей части) программы CoreNLP (в интерактивном режиме) в SBCL Lisp.

Прежде всего, забудьте использовать (sb-ext:run-program ...). Эта комбинация нереста Java с котируемым аргументом (например, звездочкой), независимо от того, насколько хорошо сбежала, просто делает аварийную сбой программы.

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

Первоначально принятое решение использовать именованные каналы Unix заканчивается тем, что является окончательным, но потребовалось немного работы, сначала с буферизацией, затем с порядком операций и, наконец, понимая некоторые нюансы о программе парсера.

Во-первых, выключая буферизацию полностью при запуске программы имеет важное значение, так работает это выглядит следующим образом:

stdbuf --i=0 --o=0 --e=0 cat ./spin | /usr/bin/java -cp "*" -Xmx2g edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,pos,lemma,ner,parse,dcoref -outputFormat text > ./spout & 

Это должен быть запущен анализатор в фоновом режиме приема входных данных от спина и отправки его выход вылить. Но если вы посмотрите на таблицу процессов в Linux, вы ее не увидите. Он все еще ждет, когда что-то вытащит из выходной трубы, прежде чем он сможет даже запустить.

Итак, мы запускаем SBCL и запустить поток вытягивать из parser's трубы:

(defparameter *from-corenlp* (open "./spout")) 

Теперь анализатор начинает работать. Здесь, как ни странно, он также запускает вывод данных на экран, а не в трубку! Это потому, что все эти материалы баннера, когда парсер запускается и останавливается (и, видимо, даже приглашение NLP>), отправляются на stderr, а не на stdout. На самом деле это хорошо.

Итак, мы объявляем поток из Лиспа анализатора:

(defparameter *to-corenlp* (open "./spin" :direction :output :if-exists :append)) 

Затем мы посылаем некоторый текст для синтаксического анализа для анализа:

(write-line "This is the first test." *to-corenlp*) 

Я столкнулся с проблемой здесь несколько раз , даже.Помните, что Лисп имеет свой собственный буфер, так что вы должны очистить поток каждый раз, когда:

(finish-output *to-corenlp*) 

Затем вы можете запустить эту строку ниже целой кучи раз, чтобы убедиться, вы получите точно такое же поведение, которое вы получили бы от интерактивная сессия парсер:

(format t "~a~%" (read-line *from-corenlp*)) 

Что, если вы хороший мальчик разведчик, должно быть не только верно, но вы можете носить с вашей интерактивной сессией ведомого парсера, пока вам нравится:

(write-line "This is the second test." *to-corenlp*) 
(finish-output *to-corenlp*) 

Разве это не здорово? И заметите, что я вытащил все это из-за ужаса в Unix, ужасного в Lisp и страшного бойскаута!

Теперь так же, как и вы!

+1

Если это сработало, подумайте о том, чтобы принять ваш ответ –