【问题标题】:Make execution stop on error in RStudio / Interactive R session在 RStudio / Interactive R 会话中因错误而停止执行
【发布时间】: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 它经常出现在数据科学领域。人们有很长的数据清理和组织脚本,并希望添加完整性检查以确保当他们在某一时刻更改内容时,不会在其他地方搞砸他们的数据。只需进行少量检查以确保观察次数仍然正确,或者唯一标识符仍然是唯一的。

标签: r unit-testing testing rstudio read-eval-print-loop


【解决方案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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-15
        • 2016-12-30
        • 1970-01-01
        • 2022-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多