【问题标题】:Accessing R objects from subprocess into parent process将 R 对象从子进程访问到父进程
【发布时间】:2018-04-27 09:04:57
【问题描述】:

在教授 R 编程的背景下,我试图完全独立地运行 R 脚本,以便我可以比较它们生成的对象。

目前,我在 R 环境中执行此操作:

student_env <- new.env()
solution_env <- new.env()

eval(parse(text = "x <- 4"), env = student_env)
eval(parse(text = "x <- 5"), env = solution_env)

student_env$x == student_env$y

虽然这提供了一些封装,但到目前为止是完整的。例如,如果我在学生环境中执行 library() 调用,它会附加到全局 R 会话的搜索路径,从而使包也可用于在解决方案环境中运行的代码。

为确保完全分离,我可以使用 subprocess 包启动子流程:

library(subprocess)
rbin <- file.path(R.home("bin"), "R")
student_handle <- spawn_process(rbin, c('--no-save'))
solution_handle <- spawn_process(rbin, c('--no-save'))

process_write(student_handle, "x <- 4\n")
process_write(solution_handle, "x <- 5\n")

但是,我不确定如何执行获取 R 对象的步骤,以便可以比较它们。

我的问题:

  • subprocess 是个好方法吗?
  • 如果是,我如何(有效地!)从子进程中获取对象的 R 表示,以便比较父进程中的对象? Python 通过酸洗/挖掘来做到这一点。
    • 我可以通过 .rds 文件进行通信,但这是不必要的文件创建/读取。
    • 在 R 中,我遇到了 RProtoBuf,但我不确定它是否能解决我的问题。
  • 如果不是,我应该考虑其他方法吗?我研究了opencpu,但启动本地服务器然后使用 R 与该服务器通信并获取表示的概念感觉过于复杂。

谢谢!

【问题讨论】:

  • ...你为什么要这样做?
  • 也许让您的学生在 .Rdata 文件中提交他们的答案(使用 savesave.image 创建)?然后你可以将他们的答案加载到单独的环境中进行比较?
  • @chinsoon12 我确实可以运行每个脚本并将工作区保存在 .RData 文件中,然后将 .RData 文件导入主 R 进程,但我想知道是否有更直接的,更清洁的方式。

标签: r subprocess protocol-buffers environment opencpu


【解决方案1】:

另一种可能的方法是callr 包,它很受欢迎,并且由可靠来源开发:https://github.com/r-lib/callr#readme

一个例子:

r(function() var(iris[, 1:4]))

#>              Sepal.Length Sepal.Width Petal.Length Petal.Width
#> Sepal.Length    0.6856935  -0.0424340    1.2743154   0.5162707
#> Sepal.Width    -0.0424340   0.1899794   -0.3296564  -0.1216394
#> Petal.Length    1.2743154  -0.3296564    3.1162779   1.2956094
#> Petal.Width     0.5162707  -0.1216394    1.2956094   0.5810063

【讨论】:

  • dash2,有趣的包,感谢分享。但是,它不允许我从子进程中获取实际对象以在父进程中使用。相反,它会打印出子流程中生成的调用的输出。
  • 呃,不是吗?正如文档的第一行所声称的,r 函数“无缝返回结果”。如果它不适合您,请报告错误。
  • 你说得对,对不起。我将深入研究是否有办法在整个程序执行过程中保持对子进程的引用,以便稍后从中获取对象。谢谢!
  • 我相信callr 在单独的进程中运行每个命令,并在命令完成后结束它。我会看看processx 包,它似乎有一个非常丰富的API。在我写 subprocess 的时候它还不存在,但现在它似乎已经超过了我的包的功能。
【解决方案2】:

我会使用RServe,因为它允许您运行多个 R 会话并从主 R 会话控制它们。您可以在这些会话中以任何给定(交织)顺序运行命令并访问以本机格式存储在那里的对象。

subprocess 已被创建为通过其命令行界面运行和控制任意程序,因此我从未打算添加对象传递机制。虽然,如果我要从子进程访问对象,我会通过 saveRDSreadRDS 来完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2017-08-09
    • 2016-03-31
    相关资源
    最近更新 更多