从R中退出并重新启动一个干净的R会话?

110

我是否可以在 R 中创建一个别名,使其执行 q() 然后重新启动一个干净的 R 会话?

是的,我太懒了,不想输入 q() 然后再输入字母 R :)


你可以使用rm(list=ls())来清除你的工作空间,但这不是你的意思对吧? - Sacha Epskamp
2
您是否也想要分离任何已附加的软件包和其他物品? - Spacedman
2
也许一个建议是在 q() 中添加一个新的选项 save 参数,例如 "r",它可以在不保存工作区的情况下重新启动 R。然后可以为 q("r") 分配一个别名到一个新函数,该函数重新启动 R。 - Greg
13个回答

110

如果您使用的是RStudio: 按下命令/ctrl + shift + F10

您也可以使用

.rs.restartR()

21
我认为打开一个“清洁的R会话”需要满足以下两个条件:1-删除当前会话中的数据;2-卸载当前会话中的软件包。在我的电脑上,.rs.restartR()似乎没有执行这些操作。 - steadyfish
5
我认为.rs.restartR()函数非常有用,可以在R即使执行remove(list=ls()); gc();操作后仍无法释放内存时使用。这个函数可以确保释放内存。另外,我也喜欢它不会分离包的特点。 - Richard DiSalvo
@RichardDiSalvo:但问题是:这有帮助吗?据我了解,未释放的空间是为了让R在需要时能够后续使用。因此,如果以后需要这些空间,R可以直接使用,而不需要再次申请内存。那么,这样真的能加快速度吗? - undefined
@lrgendniemand 我认为如果你想弄清楚你的计算机是否真的快没有内存了,或者只是R程序占用了太多内存,这可能会有所帮助。但我认为可能有更好的方法。 - undefined

63

根据你如何启动R,尝试将以下一行代码之一放入你的.Rprofile文件中:

makeActiveBinding("refresh", function() { shell("Rgui"); q("no") }, .GlobalEnv)

makeActiveBinding("refresh", function() { system("R"); q("no") }, .GlobalEnv)

然后在 R 控制台中输入:

refresh

将关闭当前会话并启动新会话。


4
或者.Last <- function() system("R")甚至在关闭周期晚些时候reg.finalizer(.GlobalEnv, function(e) system("R"), TRUE),然后q()会不断返回。 - Martin Morgan
1
确保 R 已经添加到你的 PATH 环境变量中。 - G. Grothendieck
3
这个解决方案可行,但在他人运行我的脚本时无法重现。是否有一个可以包含在R脚本中的命令来重新启动R会话?(原因是我希望所有的包都被卸载)。Translated: This solution is effective, but cannot be reproduced when others run my script. Is there a command that can be included in the R script to restart the R session? (The reason is that I want all packages to be uninstalled.) - Heisenberg
q("no")的目的是什么?如果我只在VS Code中运行system("R"),会话似乎重新启动得很好(变量被删除并且包被分离,然后开始一个新会话)。 - M. Rodo
1
这将不会关闭当前会话并启动一个新会话,而是在当前会话之上启动一个新会话。直到您退出新会话,"旧"会话才会退出。这意味着旧会话中正在使用的所有内存仍将保持“正在使用”状态,如果在某些情况下不需要或有问题,则可能不希望出现这种情况... - Chris

16

我发现.rs.restartR()与按下ctrl+shift+F10类似,但不会卸载程序包。


可以在RStudio中使用,但我不确定是否有办法让它在其他地方工作。从getAnywhere(".rs.restartR")中可以看出它在tools:rstudio中。我在纯R会话中没有成功访问过它。 - Gregor Thomas
13
.rs.restartR()不能卸载已加载的软件包,因此它与ctrl+shift+f10不是完全相同的。 - Arthur
请注意,.rs.restartR() 会将环境中的对象和包重新加载到重新启动的会话中。 - Rasmus Larsen

13
作为另一种选择,Emacs ESS(>= 16.10)可以通过默认绑定到 C-c C-e C-rinferior-ess-r-reload-hook重新加载次级 R 进程。

运行良好!非常出色! - agent18

6

在寻找解决方案后,我根据这里的解决方案使用了R包RDCOMClient来解决我的问题。
以下解决方案仅适用于RStudio(Windows),因为它模拟了按下ctrl+ shift + F10键。

必须使用以下命令安装RDCOMClient软件包:

install.packages("RDCOMClient", repos = "http://www.omegahat.net/R")

在RStudio(Windows 10)中模拟按键的代码为:
library(RDCOMClient) 
wsh <- COMCreate("Wscript.Shell") 
wsh$SendKeys("^+{F10}") 

在上述代码的最后一行中,'ctrl'键由'^'表示,shift键由'+'表示。所有关于这些键的表示法的解释都可以在这里找到。
在运行上述代码的最后一行之后,整个RStudio中的R会话将被重置,根据@steadyfish的评论。也就是说,它会从当前会话中删除所有数据并卸载会话中加载的所有软件包。

5

虽然这是旧帖子,但是没有一个答案适合我(我使用的是Windows,没有测试其他操作系统),所以我会添加我的解决方案。这里可能有些术语不准确,但是应该可以理解:

以上答案不能完全解决问题

在这里提交的大部分答案都涉及使用shellsystem,但是这并不能完全解决问题,因为虽然它们会打开一个新的R控制台并指示原始控制台关闭,但是新的控制台是在旧控制台的应用程序上下文中运行的进程。这意味着在新的控制台关闭之前,原始控制台无法关闭。像hedgedandlevered等用户报告说,关闭原始控制台会强制新的控制台关闭。当我尝试时,新的控制台确实会打开,但旧的控制台仍然以冻结状态保持打开状态,直到新的控制台关闭。

基本问题在于调用shellsystem不会将应用程序上下文从原始控制台更改为新控制台,因此原始进程无法终止,直到新控制台关闭。

适用于我的替代方案

相反,使用shell.exec,这通常用于根据文件类型在默认应用程序中打开文件。当在.exe上使用时,它会运行可执行文件。然而,重要的区别是系统会在其自己的单独上下文中启动应用程序。因此,以下是适用于我的代码:

makeActiveBinding("restart.R", function() { shell.exec(paste0(R.home(),"/bin/x64/Rgui.exe")); q("no") }, .GlobalEnv)

您需要编辑文件路径/bin/x64/Rgui.exe,以匹配您用于启动R的内容。将此行放入您的.Rprofile文件中,然后您可以通过在R代码中输入restart.R来调用它。
与其他方法相比,这种方法的缺点是您无法像使用shell那样传递命令行参数,例如--no-save,但至少这将让您关闭原始的R进程。

2

请在您的.Rprofile文件中编写此函数。

r <- function() {
  assign('.Last',  function() {system('R')}, envir = globalenv())
  quit(save = 'no')
}

r() 重启 R 会话。已加载的包不会重新加载。你的环境不会被保存。

仅适用于 Linux 系统。对其他操作系统的使用效果未知。


1

我需要在Windows上实现相同的刷新会话功能,最终得到了稍微修改过的代码:

makeActiveBinding("refresh", function() { shell(paste0("start \"\" \"", R.home(), "/bin/x64/Rgui.exe\"")); q("no") }, .GlobalEnv)

在Windows上,您需要修改Rprofile.site文件。它位于R的etc目录下。还要注意路径的最后一部分,bin/x64可能会根据您的系统配置而改变。我希望这能帮助其他人。

1
我认为,通过在选项中设置当前工作目录,可以实现最佳使用R。然后,每当您的工作区/会话文件开始显示出来或其中有足够的工作(在项目之间),您只需在关闭R之后将默认会话文件重命名为工作目录中的新名称,R/Rstudio将自动启动新的工作区/会话文件,而不会干扰您当前的工作。
记得退出R并重命名当前会话文件。
当然,如果您不想保存当前工作,您必须确保重置对象或对它们进行的操作是从原始对象复制的,以便它们保持原样。相信我,知道您始终可以加载旧的工作区是一种诱惑,但比不知道更有用。
简而言之,退出R,这样可以给您一些空间,同时意味着此工作区已满,完成退出后将其重命名并重新启动R/Rstudio,以获得新的工作区。您始终可以在新的工作区中加载选择的对象。理想情况下,所有重要的工作都应该在项目目录中,但是您仍然需要一个作业历史记录,以便在某些时候返回,并且保存的会话在长期项目中某个时候会很有用。如果您不需要任何内容,只需rm(list=ls())

另外,我喜欢@Eduardo Alvin提出的RDComClient想法,但它已经停止支持。

备选方案

在您的工作区内随时摆脱负担的简单替代方法是使用save.image

save.image("Rstreamingscience.data")
quit(save='no')
load("Rstreamingscience.data") ##G:/ADA registers##
save.image("Rstreamingscience.data")

这让你可以自由出入,随心开启所需数量的工作区。

1

按照Martin Morgan的想法,使用.Last()重新启动R,并使用与先前调用相同的命令行选项:

restart_r <- function(status = 0, debug = TRUE) {
  if (debug) message("restart_r(): Customizing .Last() to relaunch R ...")
  assign(".Last", function() {
    args <- commandArgs()
    system2(args[1], args = args[-1])
  }, envir = globalenv())   
  if (debug) message("restart_r(): Quitting current R session and starting a new one ...")
  quit(save = "no", status = status, runLast = TRUE)
}

2
顺便提一下,我已经将 startup::restart() 添加到 startup 包中,作为重新启动 R 的方便方式。 - HenrikB

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