Передать выражения в 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)