在 RStudio / Interactive R 会话中因错误而停止执行

Posted

技术标签:

【中文标题】在 RStudio / Interactive R 会话中因错误而停止执行【英文标题】:Make execution stop on error in RStudio / Interactive R session 【发布时间】:2017-07-04 12:31:32 【问题描述】:

在 RStudio 中执行代码块时,发生错误时执行实际上并没有停止。例如,如果我在打开的编辑器中有以下代码:

x <- 'test'
stopifnot(is.numeric(x))
print('hello world')

并运行它(使用命令返回或单击“运行”按钮),它会打印错误,然后继续执行打印语句。

有没有办法将 RStudio 配置为不继续出错?即让它在上面的第 2 行停止而不继续打印语句?

编辑:刚刚意识到,如果我使用 command-R 在标准 R GUI 中发送代码块,也会发生这种情况。

【问题讨论】:

如果您将其作为源文件执行,那么它将按照您的意愿工作。例如,如果您将 3 行代码复制并粘贴到控制台并按 Enter,那么它将分别运行每一行代码。第二种模式很可能是运行按钮的操作方式。 @lmo 谢谢——问题是我认识的大多数人都是交互式编程的。我正在尝试为社会科学家编写一个教程,以便在他们的代码中进行测试,并且需要在他们所在的地方满足他们。 总是有tryCatchtry 感谢@Dason 的评论,我刚刚想到的一个技巧:如果您将代码括在大括号中, R 将像执行单个命令一样执行该块,那么您将获得您的想要的结果。 @Dason 它经常出现在数据科学领域。人们有很长的数据清理和组织脚本,并希望添加完整性检查以确保当他们在某一时刻更改内容时,不会在其他地方搞砸他们的数据。只需进行少量检查以确保观察次数仍然正确,或者唯一标识符仍然是唯一的。 【参考方案1】:

当您选择一个部分并按 Ctrl+Enter 时,我认为没有办法阻止 RStudio 运行所有行。 Rstudio 只是一条接一条地运行。即使在函数内部调用stopifnot(),该函数调用之后的所有行仍将被计算。

如果您的目标只是在出现问题时得到通知,在大量代码徒劳无功之前,也许您可​​以定义一个类似于 stopifnot() 的函数,如果有错误。然后,您可以按Esc 或 RStudio 中的停止按钮来中断程序。像这样的:

waitifnot <- function(cond) 
  if (!cond) 
    message(deparse(substitute(cond)), " is not TRUE")  
    while (TRUE) 
  

现在,您可以使用此函数运行示例代码:

x <- 'test'
waitifnot(is.numeric(x))
print('hello world')

正如预期的那样,hello world 永远不会被打印出来。您将收到一条错误消息,告诉您出了点问题,然后程序将等待您手动中止它。

这在交互模式以外的任何情况下都无法正常工作。为了避免不愉快的情况,你也可以让函数做出不同的反应,如果它没有在交互模式下使用,例如这样:

waitifnot <- function(cond) 
  if (!cond) 
    msg <- paste(deparse(substitute(cond)), "is not TRUE")
    if (interactive()) 
      message(msg)
      while (TRUE) 
     else 
      stop(msg)
    
  

只有在交互模式下运行时,此函数才会进入无限循环。否则,它将通过调用stop() 简单地中止执行。我已经检查了使用 Ctrl+Enter 或 RStudio 中的 Source 按钮(无限循环)以及 Bash 命令行上的 Rscript(程序中止)是否可以正常工作。

【讨论】:

【参考方案2】:

正如@lmo 所述,您只需点击按钮Source 而不是全选+Run。事实上,您甚至不需要保存脚本文件就能点击Source 按钮。

但问题确实是Source 将始终运行整个脚本。所以如果你真的只想在脚本中运行一个块,这对你没有帮助。

【讨论】:

【参考方案3】:

解决此问题的一种方法是配置 R 'error' 选项以在遇到错误时运行自定义函数。

一个示例错误处理函数可以使用 Sys.sleep 暂停 R 的执行并等待用户输入(例如,通过按 ctrl-C 或在我的 Mac 上的 R-Studio 中按 Escape 退出正在运行的函数)。

通常,R 将继续前进并执行任何后续命令。但是,我们可以通过定义一个“吃掉”所有这些的函数来防止这种情况发生,这样它们就不会运行。为了使这个更流畅,我们可以在每个“吃掉”行之后输出一个“光标向上”字符序列,在输出下一个时擦除它们中的每一个,这样未运行的行就不会弄乱终端/控制台。

示例代码:

# Define our error-handling pause function:

pause=function()
    on.exit(eat_input())
    cat("Paused: press ctrl-C (or Escape key in Rstudio) to continue\n")
    cat("(any subsequent code will be ignored)\n")
    Sys.sleep(Inf)


# Define our 'eat_input' function to prevent output of subsequent, not-run input:

eat_input=function()
    cat("\033[1A")
    while((x=readline())!='')cat("\033[1A")


# Set the 'error' option to execute our pause function:

options(error=pause)

试试看:

print("Before the error")

# an error: we want to stop after this
xxx

# some more input: we don't want this to be run or to appear in the console
print("After the error")

要关闭此行为,只需将错误选项重新设置为NULL

options(error=NULL)

【讨论】:

以上是关于在 RStudio / Interactive R 会话中因错误而停止执行的主要内容,如果未能解决你的问题,请参考以下文章

带有 rstudio 的新版本 R

启动 R/RStudio 时不需要加载 R 中的包?

rstudio控制台和脚本区的区别

R.003 Rstudio使用

RStudio 未检测到已安装的 R

R语言入门1:安装R和RStudio