Передать выражения в evalServer

С пакетом svSocket Я пытаюсь выполнить на сервере универсальное выражение

expr <- "demo<-new.env()"
evalServer(con, expr, expr)
> evalServer(con, parse(text=expr))
Error in source(objcon, local = TRUE, echo = FALSE, verbose = FALSE) : 
  objcon:1:65: unexpected '<'
1: ..Last.value <-structure(expression(demo<-new.env()), srcfile = <

Как я могу избежать этого? PS: мне нужно программно создать объект на сервере. например demo будет исходить из пользовательского ввода и вставить ()d в приведенную выше строку.

Воспроизводимый пример ### Открой две rsession

# run in the 1st rsession
require(svSocket)
startSocketServer()

# run in the 2nd rsession
con <- socketConnection(host = "localhost", port = 8888, blocking = FALSE)
expr <- "demo<-new.env()"
evalServer(con, expr, expr)

1 ответ

Решение

Вот обходной путь для того, что вы хотите сделать.

Сначала запустите R с сервером сокетов в окне терминала:

$ R
> require(svSocket)
> startSocketServer()
> 

Затем в другом процессе R загрузите svSocket, подключитесь к серверу сокетов и используйте evalServer():

$ R
> require(svSocket)
> options(prompt = "RClient> ")
RClient> con <- socketConnection(host = "localhost", port = 8888, blocking = FALSE)

Сейчас, evalServer() работает путем сериализации-десериализации объектов R с целью отправки их через сокет. Не все объекты R являются сериализуемыми... и среды относятся к тем объектам, которые вызывают проблемы.

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

RClient> evalServer(con, expr, "demo <- new.env(); NULL")

Затем вы должны дать команду серверу проанализировать и оценить этот код на его стороне. От клиента:

RClient> evalServer(con, eval(parse(text = expr)))

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

RClient> evalServer(con, ls())
[1] "demo" "expr"
RClient> evalServer(con, class(demo))
[1] "environment"
RClient> 

И, конечно же, вы также должны позаботиться о том, чтобы манипулировать "демо" от клиента. Не забудьте в конце:

RClient> close(con)
Другие вопросы по тегам