在 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 谢谢——问题是我认识的大多数人都是交互式编程的。我正在尝试为社会科学家编写一个教程,以便在他们的代码中进行测试,并且需要在他们所在的地方满足他们。 总是有tryCatch
和try
。
感谢@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 会话中因错误而停止执行的主要内容,如果未能解决你的问题,请参考以下文章