nic*_*_eu 12 testing unit-testing r rstudio
在RStudio中执行代码块时,执行实际上不会在发生错误时停止.例如,如果我在打开的编辑器中有以下代码:
x <- 'test'
stopifnot(is.numeric(x))
print('hello world')
Run Code Online (Sandbox Code Playgroud)
并运行它(使用命令返回或单击"运行"按钮),它会打印错误,然后继续前进并执行print语句.
有没有办法配置RStudio不能超过错误?即使它停在上面第2行并且不进入打印声明?
编辑:刚刚意识到如果我使用command-R在标准R GUI中发送代码块,也会发生这种情况.
小智 6
解决此问题的一种方法是配置 R'error'选项配置为在遇到错误时运行自定义函数。
错误处理函数示例可以使用以下命令暂停 R 的执行Sys.sleep并等待用户输入(例如,通过按 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)
Run Code Online (Sandbox Code Playgroud)
试试看:
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")
Run Code Online (Sandbox Code Playgroud)
要关闭此行为,只需将错误选项重新设置为NULL:
options(error=NULL)
Run Code Online (Sandbox Code Playgroud)
我认为当您选择一个部分并按 Ctrl+Enter 时,没有办法阻止 RStudio 运行所有行。Rstudio 只是一行一行地运行。即使stopifnot()在函数内部调用,该函数调用之后的所有行仍将被评估。
如果您的目标只是在出现问题时得到通知,在大量代码徒劳运行之前,也许您可以定义一个类似于该函数的函数,stopifnot()如果出现错误,该函数将进入无限循环。然后您可以按Esc或 RStudio 中的停止按钮来中断程序。像这样的东西:
waitifnot <- function(cond) {
if (!cond) {
message(deparse(substitute(cond)), " is not TRUE")
while (TRUE) {}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用此函数运行示例代码:
x <- 'test'
waitifnot(is.numeric(x))
print('hello world')
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,hello world从未被打印。您将收到一条错误消息,告诉您出现问题,然后程序将等待,直到您手动中止它。
除了交互模式之外,这在任何情况下都无法正常工作。为了避免不愉快的情况,如果不在交互模式下使用,您还可以让函数做出不同的反应,例如如下所示:
waitifnot <- function(cond) {
if (!cond) {
msg <- paste(deparse(substitute(cond)), "is not TRUE")
if (interactive()) {
message(msg)
while (TRUE) {}
} else {
stop(msg)
}
}
}
Run Code Online (Sandbox Code Playgroud)
仅当在交互模式下运行时,该函数才会进入无限循环。否则,它将简单地通过调用 来中止执行stop()。我已经检查过使用 Ctrl+Enter 或 RStudio 中的“源”按钮(无限循环)以及RscriptBash 命令行(程序中止)是否按预期工作。