Может ли консоль R поддерживать фоновые задачи или прерывания (обработка событий)?

Работая в консоли R, я хотел бы настроить фоновую задачу, которая отслеживает конкретное соединение, и когда происходит событие, выполняется другая функция (предупреждение). В качестве альтернативы я могу настроить так, чтобы внешняя функция просто отправляла предупреждение в R, но это, похоже, та же проблема: необходимо настроить прослушиватель.

Я могу сделать это в специальном процессе R, но я не знаю, возможно ли это из консоли. Кроме того, я не заинтересован в прерывании R, если он вычисляет функцию, а в предупреждении или прерывании, если консоль просто ожидает ввода.

Вот три варианта использования:

  1. Самый простой пример — просмотр файла. Предположим, что у меня есть файл с именем «latestData.csv», и я хочу отслеживать его изменения; при его изменении выполняется myAlert(). (Можно расширить его, чтобы делать разные вещи, но полезно просто всплывать с примечанием о том, что файл изменился.)

  2. Монитор другого типа будет следить за тем, не хватает ли данной машине оперативной памяти, и может выполнить save.image() и завершить работу. Опять же, это может быть простая проблема просмотра файла, созданного внешним монитором, который сохраняет вывод top или какой-либо другой команды.

  3. Другой пример похож на другой недавний вопрос SO: есть R остановить машину EC2, на которой он работает. Если оповещение от другого компьютера или процесса говорит программе сохранить и завершить работу, то было бы здорово иметь возможность прослушивать это оповещение.

На данный момент я подозреваю, что есть два способа справиться с этим: через Rserve и, возможно, через fork. Если у кого-то есть примеры того, как это сделать с помощью пакета или другого метода, это было бы здорово. Я думаю, что решение любого из этих трех вариантов использования решит их все, по модулю небольшого количества внешнего кода.


Примечание 1: я понимаю, за этот ответ на другой вопрос SO что R является однопоточным, поэтому я подозреваю, что fork и Rserve могут работать. Однако я не уверен в возможности взаимодействия с R-терминалом. Хотя REPL R привязан к вводу из консоли, я пытаюсь либо обойти это, либо сымитировать, где ответом может быть fork или Rserve.

Примечание 2. Для тех, кто знаком с методами обработки/обработки событий, это тоже решит все проблемы. Я просто не нашел ничего об этом в R.


Обновление 1: я обнаружил, что руководство по написанию расширений R есть раздел, посвященный обработке событий, в котором упоминается использование R_PolledEvents. Это выглядит многообещающе.


person Iterator    schedule 03.09.2011    source источник


Ответы (4)


Это зависит от того, хотите ли вы прервать бездействие или работу R. Если первое, вы можете подумать об обходе цикла REPL R по умолчанию с помощью некоторого прослушивателя событий, который будет ставить в очередь входящие события и оценивать их. Распространенным вариантом является использование цикла tcl/tk или gtk; Я сделал нечто подобное для libev в своем пакете triggr, который заставляет R переваривать запросы, поступающие из сокета.

Последний случай в большинстве случаев безнадежен, если только вы не заставите вычислительный код периодически выполнять if(evenOccured) processIt код.

Многопоточность не является реальным вариантом, потому что, как вы знаете, два интерпретатора в одном процессе сломают себя, используя одни и те же глобальные переменные, в то время как разветвленные процессы будут иметь независимое содержимое памяти.

person mbq    schedule 03.09.2011
comment
Не могли бы вы пояснить свой 2-й абзац? Я рад, что что-то периодически проверяет состояние. +1 за предложения по tcl/tk и gtk. Я обязательно посмотрю на triggr и посмотрю, смогу ли я адаптировать его или идеи. - person Iterator; 03.09.2011
comment
Я посмотрел на triggr, но полагаю, мне нужно будет посмотреть на методы tcl/tk или gtk, как вы предлагаете. - person Iterator; 07.09.2011

Еще один вариант — это пакет svSocket. Он неблокирующий.

Вот 8-минутное видео с его использованием, которое набрало более 3000 просмотров. В нем показано, как превратить сеанс R в сервер и как отправлять на него команды и получать данные обратно. Он демонстрирует это, даже когда сервер занят; например, скажем, вы запускаете длительный процесс и забыли сохранить промежуточные результаты, вы можете подключиться к серверу и получить результаты (до его завершения) с него.

person Matt Dowle    schedule 08.09.2011
comment
+1 Спасибо! Похоже, это как раз то, что я ищу. Интересно, использовал ли я его раньше, поскольку его поведение похоже на то, что я имел в виду. Я дам ему вихрь и посмотреть, если он работает. - person Iterator; 09.09.2011

Оказывается, пакет Rdsm тоже это поддерживает.

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

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

Если серверный процесс, скажем, регулярно отслеживает соединение (файл, канал, URL-адрес и т. д.) и сталкивается с триггером, он может отправить сообщение клиентам.

Хотя основной целью пакета является разделяемая память (именно так я наткнулся на нее), этот обмен сообщениями неплохо работает и для других целей.


Обновление 1: Конечно, для передачи сообщений нельзя игнорировать MPI и пакет Rmpi. Это может помочь, но пакет Rdsm запускается/работает с консолями R, а именно такой интерфейс я искал. Я еще не уверен, что поддерживает Rmpi.

person Iterator    schedule 07.09.2011

Несколько идей:

  1. Запустите R из сценария другого языка (это возможно, например, в Perl с помощью RSPerl) и используйте скрипт-обертка для запуска слушателя.

  2. Другим вариантом может быть запуск внешней (не R) команды (с использованием system()) из R, которая запустит прослушиватель в фоновом режиме.

  3. #P4# #P5#
    #P6#
    #P7#
person Itamar    schedule 03.09.2011