如何使我的R会话变为vanilla?

9
这是对之前问题的澄清跟进:如何确保同一服务器上不同用户使用相同的R环境? 我想从R内部进入“vanilla” R会话,例如类似于使用命令R --vanilla启动R所获得的内容。例如,我想编写一个脚本,不受特定用户的自定义设置的影响。
特别是,我希望以下内容:
  • 不读取R历史、配置文件或环境文件
  • 不重新加载以前会话中的数据或对象
help("vanilla")没有返回任何内容,而我对自定义设置的范围不太熟悉,不知道如何退出所有这些设置。
有没有办法进入新的“vanilla”环境?(?new.env似乎没用)

你能澄清一下你在这里的预期用途吗?从你的问题中我无法确定所涉及的脚本是在现有的R会话内运行还是直接从命令行运行。 - joran
这个链接可能与编程有关:https://dev59.com/-2ct5IYBdhLWcg3wIqDW#12323852 - GSee
@joran 我希望相关脚本能够确保一个标准环境,我可以在脚本中控制,无论是从命令行运行脚本还是在现有的 R 会话中使用 source 调用脚本;无论哪种方式,我都不能确保它将在纯净环境中运行。 - David LeBauer
请注意,callr包可以让您在当前会话中启动一个新的R进程。它有一个名为r_vanilla()的函数。 - jena
2个回答

7

在我看来,可重复的研究交互式会话不太搭配。你应该考虑编写可从命令行调用而非打开交互式会话的可执行脚本。在脚本顶部的shebang中添加--vanilla

#!/path/to/Rscript --vanilla

如果您的脚本需要读取输入(参数或选项),您可以使用?commandArgs或两个包之一getoptoptparse从命令行解析它们。

如果用户真的需要在交互式会话中自己完成工作,那么他仍然可以通过system()调用您的脚本:您的脚本仍将使用自己的基础会话。只需额外做一点工作来传递输入和输出即可。


+1 -- 我很喜欢这种方法,比David在这里尝试的要好得多。 - Dirk Eddelbuettel
我同意 OP 在评论中提到的要求,即无论脚本是通过 Rscript 运行还是通过 source 运行都不应该有影响,这会使事情变得棘手。如果需要确保在启动 R 时设置了环境变量怎么办?例如,如果需要确保设置了 TMPDIR,而您无法控制用户的 .Renviron 文件?这是否可以在 shebang 中完成,或者必须像 TMPDIR="~/tmp" Rscipt --vanilla 这样在命令行中设置? - GSee
无法与Rscript交互,但可以告诉littler在非交互模式下复制R的行为。 - Dirk Eddelbuettel
1
@Gsee,“--vanilla”是“--no-save --no-restore --no-site-file --no-init-file --no-environ”的别名。你可以去掉“--no-site-file”,这样可以在启动时允许源代码调用你的“Rprofile.site”文件。在那个文件中,你可以使用“Sys.setenv()”设置“TMPDIR”。你也可以让脚本自己设置该变量。 - flodel
@Gsee,谢谢,你是对的。你可以删除 --environ,但它会读取用户和站点环境文件,所以对于多用户可重复研究来说仍然很危险。?Startup确实提到了一个与用户和站点环境文件不同的R_HOME/etc/Renviron。我测试过了,它可以工作,所以我想你也可以在站点级别使用它。否则,你的方法也可以被包装在一个shell脚本中。 - flodel
显示剩余4条评论

5

您不能只是简单地使当前会话变为vanilla,但您可以从R中开始一个新的vanilla R会话,如下所示:

> .Last <- function() system("R --vanilla")
> q("no")

我认为您使用上述代码可能会遇到问题,因为在R重新启动后,脚本的其余部分将不会执行。使用以下代码,R将在退出之前运行.Last.Last将告诉它重新启动而不读取站点文件或环境文件,并且不打印启动消息。 重新启动后,它将运行您的代码(以及进行一些其他清理工作)。
wd <- getwd()
setwd(tempdir())
assign(".First", function() {
  #require("yourPackage") 
  file.remove(".RData") # already been loaded
  rm(".Last", pos=.GlobalEnv) #otherwise, won't be able to quit R without it restarting
  setwd(wd)
  ## Add your code here
  message("my code is running.\n")
}, pos=.GlobalEnv)

assign(".Last", function() {
  system("R --no-site-file --no-environ --quiet")
}, pos=.GlobalEnv)
save.image() # so we can load it back when R restarts
q("no") 

你可能需要将你的代码放在一个名为.First的函数中,并将.First保存在工作目录下的.RData文件中。否则,重启后可能无法运行代码。 (您还需要在.First函数内删除.Last,以便稍后能够退出R而不会重新启动。)请参见我在您的问题评论中提供的链接 - GSee
如我上面所提到的,callr包可以让你在当前会话中启动一个新的R进程。它有一个名为r_vanilla()的函数。 - jena

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接