Решение, как я отправил его в список парсер рассылки Стэнфорде (переполнение стека переформатировать много его на что-то странное, но вы получите идею):
Прошло довольно много времени, но я наконец-то понял, (по большей части) программы 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 и страшного бойскаута!
Теперь так же, как и вы!
* «Это как должно работать?» * Нет. Простой тест с «cat/dev/random> fifo» (fifo, сделанный с mkfifo) и открытие fifo из sbcl не позволяет мне копировать вопрос. Есть ли что-нибудь еще, что вы могли бы рассказать нам об этом? – coredump
Хорошо, я подумал, что это не должно работать так. Я сделал тест, делающий кошку из файла, и результат оказался надежно на lisp-трубе. Объявление потока вывода из lisp в трубу: (defparameter to-corenlp (открыть «./spout»: direction: output: if-exists: append)) не работает. Никакие данные не поступали на принимающий конец в lisp, хотя я мог бы продолжать котировать входной файл в трубку для подачи, и данные будут поступать в поток lisp. –
Интересно, что если я запускаю программу java, отправляющую вывод в трубу, программа по-прежнему не отправляет свои данные в трубу, однако ls> spout отправляет данные в трубу и может быть надежно прочитан в lisp. Для записи я попытался использовать sb-ext: run-program, и это не сработает. Любая java-программа с указанным аргументом (например, звездочка выше) вылетает, как только она запускается. Это не происходит с нижней оболочкой, но я понятия не имею, как получить функционирующий поток из lisp в порожденную программу одновременно с чтением из порожденной программы. –