我有一个大的R脚本,比方说,142个小部分.如果一个部分失败并出现错误,我希望脚本继续而不是停止.这些部分不一定相互依赖,但有些部分相互依赖.如果中间的一个失败那没关系.我宁愿不try()
打电话给这个剧本.而且我不希望将文件拆分成许多较小的文件,因为每个部分都很短.
如果source()
可以像在R控制台上复制和粘贴一样工作,那就太好了.或者如果有办法将错误降级为警告,那也没关系.
一旦脚本运行,我打算grep(或类似)输出错误或警告文本,以便我可以看到已发生的所有错误或警告,而不仅仅是它已在第一个错误上停止.
我已经阅读?source
并搜索了Stack Overflow的[R]标签.我发现下面类似的问题,但try
与tryCatch
人的答案提供:
R脚本 - 如何在出错时继续执行代码
在收到错误消息而不是暂停执行后,是否有任何方法让R脚本继续?
我不是在寻找try
或tryCatch
出于上述原因.这不适用于R包测试,我知道测试框架以及许多try()
或test_that()
调用(或类似)完全合适的地方.这是我所描述的脚本的其他内容.
谢谢!
Jos*_*ien 22
为了使这更具体,以下怎么样?
首先,要测试该方法,请创建一个"script.R"
包含多个语句的文件(调用它),第一个语句在评估时会抛出错误.
## script.R
rnorm("a")
x <- 1:10
y <- 2*x
Run Code Online (Sandbox Code Playgroud)
然后将其解析为表达式列表,并依次评估每个元素,将评估包装在调用中,tryCatch()
以便错误不会造成太大的损害:
ll <- parse(file = "script.R")
for (i in seq_along(ll)) {
tryCatch(eval(ll[[i]]),
error = function(e) message("Oops! ", as.character(e)))
}
# Oops! Error in rnorm("a"): invalid arguments
#
# Warning message:
# In rnorm("a") : NAs introduced by coercion
x
# [1] 1 2 3 4 5 6 7 8 9 10
y
# [1] 2 4 6 8 10 12 14 16 18 20
Run Code Online (Sandbox Code Playgroud)
Jos*_*ien 14
该评估的软件包提供其另一种选择evaluate()
功能.它不像我的其他建议那么轻巧,但是 - 作为支撑编织者的功能之一- 它已经过你所希望的测试!
library(evaluate)
rapply((evaluate(file("script.R"))), cat) # For "script.R", see my other answer
# rnorm("a")
# NAs introduced by coercionError in rnorm("a") : invalid arguments
# In addition: Warning message:
# In rnorm("a") : NAs introduced by coercion
x
# [1] 1 2 3 4 5 6 7 8 9 10
y
# [1] 2 4 6 8 10 12 14 16 18 20
Run Code Online (Sandbox Code Playgroud)
对于看起来更像您在命令行中实际键入语句的输出,请使用replay()
.(感谢hadley提示):
replay(evaluate(file("script.R")))
# >
# > rnorm("a")
# Warning message:
# NAs introduced by coercion
# Error in rnorm("a"): invalid arguments
# > x <- 1:10
# > y <- 2*x
Run Code Online (Sandbox Code Playgroud)
编辑
replay()
还提供了一种更好的方式来回放错误和警告,如果这些都是你需要的:
## Capture the output of evaluate()
res <- evaluate(file("script.R"))
## Identify those elements inheriting from "error" or "warning
ii <- grepl("error|warning", sapply(res, class))
## Replay the errors and warnings
replay(res[ii])
# Warning message:
# NAs introduced by coercion
# Error in rnorm("a"): invalid arguments
# >
Run Code Online (Sandbox Code Playgroud)
这是笨重的,使用没有人的朋友,eval(parse(
但可能有点帮助..乔希的答案更清洁.
# assign the filepath
fn <- "c:/path/to your/script.R"
# read in the whole script
z <- readLines( fn )
# set a starting j counter
j <- 1
# loop through each line in your script..
for ( i in seq(length(z)) ) {
# catch errors
err <- try( eval( parse( text = z[j:i] ) ) , silent = TRUE )
# if it's not an error, move your j counter up to one past i
if ( class( err ) != 'try-error' ) j <- i + 1 else
# otherwise, if the error isn't an "end of input" error,
# then it's an actual error and needs to be just plain skipped.
if ( !grepl( 'unexpected end of input' , err ) ) j <- i + 1
# otherwise it's an "end of line" error, which just means j alone.
}
Run Code Online (Sandbox Code Playgroud)