在tryCatch中处理警告之前的错误
我正在处理一个同时抛出错误和警告的函数。 (相关:) 通常,警告会导致错误。在这些情况下,我希望忽略警告,只处理错误 另一方面,如果只有一个警告(没有错误),那么我希望捕获该警告 我正在尝试使用众所周知的易于使用的在tryCatch中处理警告之前的错误,r,exception-handling,try-catch,R,Exception Handling,Try Catch,我正在处理一个同时抛出错误和警告的函数。 (相关:) 通常,警告会导致错误。在这些情况下,我希望忽略警告,只处理错误 另一方面,如果只有一个警告(没有错误),那么我希望捕获该警告 我正在尝试使用众所周知的易于使用的tryCatch 我眼前的问题是: 有没有办法强制tryCatch在warnings之前处理errors(或者在出现错误时忽略警告) 从?tryCatch文档中我的理解是,条件是通过FIFO处理的,在这种情况下,我的直接问题的答案是否定的——至少不是直接的。在这种情况下,是否可以处理警
tryCatch
我眼前的问题是:
有没有办法强制tryCatch
在warning
s之前处理error
s(或者在出现错误时忽略警告)
从?tryCatch
文档中我的理解是,条件是通过FIFO处理的,在这种情况下,我的直接问题的答案是否定的——至少不是直接的。在这种情况下,是否可以处理警告,然后在仍然捕获错误的情况下继续该功能?
我无法获得的解决方案:
#我仍希望捕获并处理警告suppressWarnings
#某些警告是无害的选项(warn=2)
我在包中编写了一个方便的帮助函数,用于评估,它捕获所有警告、错误和打印在标准输出上的任何内容,以及调用中返回的原始R对象:
> library(pander)
> evals('F.errorAndWarning()')
[[1]]
$src
[1] "F.errorAndWarning()"
$result
NULL
$output
NULL
$type
[1] "error"
$msg
$msg$messages
NULL
$msg$warnings
[1] "Warning before the error"
$msg$errors
[1] "error"
$stdout
[1] "I have moved on."
attr(,"class")
[1] "evals"
我将编写一个函数来执行
表达式
,并对错误进行优先级排序
prioritize.errors <- local({
# this function executes an expression and stores the warnings
# until it finishes executing.
warnings <- list()
w.handler <- function(w) {
warnings <<- c(warnings, list(w))
invokeRestart('muffleWarning') # here's the trick
}
function(expr) {
withCallingHandlers({expr}, warning=w.handler)
for (w in warnings) warning(w)
warnings <<- list()
}
})
F.warning <- function() {
warning("a warning")
message('ok')
}
test <- function(expr) {
tryCatch(expr,
error=function(e) cat("ERROR CAUGHT"),
warning=function(w) cat("WARNING CAUGHT")
)
}
test(prioritize.errors(F.error()))
# ERROR CAUGHT
test(prioritize.errors(F.warning()))
# ok
# WARNING CAUGHT
test(prioritize.errors(F.errorAndWarning()))
# I have moved on.ERROR CAUGHT
prioritized.errors这与问题相关,“是否可以处理警告,然后在仍然捕获错误的情况下继续该功能?”问题
我有一个类似的问题,我想将警告和错误的日志记录功能绑定到try-catch,并在警告后始终继续,并且能够在try-catch上执行多次尝试,例如访问脆弱的网络驱动器。这就是我最后使用的。这一版本或更简化的版本可能有助于解决您的问题
MyLibrary.Sys.Try <- function(
expr, # Expression that will be evaluated by the call to Try
errorMessage="", # Optional prepended string to add to error output
warningMessage="", # Optional prepended string to add to warning output
failureMessage="", # Optional prepended string to add to failing all attempts
finally=NULL, # Optional expression to be executed at the end of tryCatch
attempts=1, # Number of attempts to try evaluating the expression
suppressError=TRUE, # Should the call just log the error or raise it if all attempts fail
quiet=FALSE # Return expression normally or as invisible
) {
tryNumber <- 0
while(tryNumber<attempts) {
tryNumber <- tryNumber + 1
# If not suppressing the error and this is the last
# attempt then just evaluate the expression straight out
if(tryNumber == attempts && !suppressError){
# NOTE: I think some warnings might be lost here when
# running in non-interactive mode. But I think it should be okay
# because even nested dispatch seems to pick them up:
# MyLibrary.Sys.Try(MyLibrary.Sys.Try(function(),suppressError=F))
return(expr)
}
tryCatch({
# Set the warning handler to an empty function
# so it won't be raised by tryCatch but will
# be executed by withCallingHandlers
options(warning.expression=quote(function(){}))
withCallingHandlers({
if(quiet) {
return(invisible(expr))
} else {
return(expr)
}
},error=function(ex){
MyLibrary.Sys.Log.Error(errorMessage,ex)
}, warning=function(warn){
# Had issues with identical warning messages being
# issued here so to avoid that only log it the first
# time it happens in a given minute.
warnStamp <- paste(Sys.time(),warn,collapse="_",sep="")
if(!identical(warnStamp,getOption("MyLibrary.LAST.WARNING"))) {
if(!(interactive() && is.null(getOption("warning.expression")))){
MyLibrary.Sys.Log.Warning(warningMessage,warn)
}
options(MyLibrary.LAST.WARNING=warnStamp)
}
})
},error=function(ex){
# Suppressing the error since it's been logged
# by the handler above. Needs to be suppressed
# to not invoke the stop directly since the
# handler above passes it through.
},finally={
# Set the warning handler to the default value
# of NULL which will cause it to revert to it's
# normal behaviour. If a custom handler is normally
# attached it would make sense to store it above
# and then restore it here. But don't need that now
options(warning.expression=NULL)
if(!is.null(finally)){
if(quiet) {
return(invisible(finally))
} else {
return(finally)
}
}
})
}
msg <- paste(ifelse(nchar(failureMessage)>0," - ",""),"Failed to call expression after ",attempts," attempt(s)",sep="")
MyLibrary.Sys.Log.Error(failureMessage,msg)
}
MyLibrary.Sys.Try这三个答案都做得非常广泛和出色,但我认为很多人也在寻找一种简短、简单的方法来处理警告,但要继续执行。这可以很快完成,如Matthew所示:通过调用重启(并使用withCallingHandlers):
测试这看起来非常有用,谢谢。我得把它消化一分钟你会用这里的答案吗?马特,我用了你和汉西的混合答案。我不知道在哪里打对勾。我将把它放在Hansi的上,因为我认为他高度评论的代码将有助于其他人的搜索——另外他还可以使用一些额外的要点:)谢谢你,谢谢你的提醒
> library(pander)
> evals('F.errorAndWarning()')
[[1]]
$src
[1] "F.errorAndWarning()"
$result
NULL
$output
NULL
$type
[1] "error"
$msg
$msg$messages
NULL
$msg$warnings
[1] "Warning before the error"
$msg$errors
[1] "error"
$stdout
[1] "I have moved on."
attr(,"class")
[1] "evals"
prioritize.errors <- local({
# this function executes an expression and stores the warnings
# until it finishes executing.
warnings <- list()
w.handler <- function(w) {
warnings <<- c(warnings, list(w))
invokeRestart('muffleWarning') # here's the trick
}
function(expr) {
withCallingHandlers({expr}, warning=w.handler)
for (w in warnings) warning(w)
warnings <<- list()
}
})
F.warning <- function() {
warning("a warning")
message('ok')
}
test <- function(expr) {
tryCatch(expr,
error=function(e) cat("ERROR CAUGHT"),
warning=function(w) cat("WARNING CAUGHT")
)
}
test(prioritize.errors(F.error()))
# ERROR CAUGHT
test(prioritize.errors(F.warning()))
# ok
# WARNING CAUGHT
test(prioritize.errors(F.errorAndWarning()))
# I have moved on.ERROR CAUGHT
MyLibrary.Sys.Try <- function(
expr, # Expression that will be evaluated by the call to Try
errorMessage="", # Optional prepended string to add to error output
warningMessage="", # Optional prepended string to add to warning output
failureMessage="", # Optional prepended string to add to failing all attempts
finally=NULL, # Optional expression to be executed at the end of tryCatch
attempts=1, # Number of attempts to try evaluating the expression
suppressError=TRUE, # Should the call just log the error or raise it if all attempts fail
quiet=FALSE # Return expression normally or as invisible
) {
tryNumber <- 0
while(tryNumber<attempts) {
tryNumber <- tryNumber + 1
# If not suppressing the error and this is the last
# attempt then just evaluate the expression straight out
if(tryNumber == attempts && !suppressError){
# NOTE: I think some warnings might be lost here when
# running in non-interactive mode. But I think it should be okay
# because even nested dispatch seems to pick them up:
# MyLibrary.Sys.Try(MyLibrary.Sys.Try(function(),suppressError=F))
return(expr)
}
tryCatch({
# Set the warning handler to an empty function
# so it won't be raised by tryCatch but will
# be executed by withCallingHandlers
options(warning.expression=quote(function(){}))
withCallingHandlers({
if(quiet) {
return(invisible(expr))
} else {
return(expr)
}
},error=function(ex){
MyLibrary.Sys.Log.Error(errorMessage,ex)
}, warning=function(warn){
# Had issues with identical warning messages being
# issued here so to avoid that only log it the first
# time it happens in a given minute.
warnStamp <- paste(Sys.time(),warn,collapse="_",sep="")
if(!identical(warnStamp,getOption("MyLibrary.LAST.WARNING"))) {
if(!(interactive() && is.null(getOption("warning.expression")))){
MyLibrary.Sys.Log.Warning(warningMessage,warn)
}
options(MyLibrary.LAST.WARNING=warnStamp)
}
})
},error=function(ex){
# Suppressing the error since it's been logged
# by the handler above. Needs to be suppressed
# to not invoke the stop directly since the
# handler above passes it through.
},finally={
# Set the warning handler to the default value
# of NULL which will cause it to revert to it's
# normal behaviour. If a custom handler is normally
# attached it would make sense to store it above
# and then restore it here. But don't need that now
options(warning.expression=NULL)
if(!is.null(finally)){
if(quiet) {
return(invisible(finally))
} else {
return(finally)
}
}
})
}
msg <- paste(ifelse(nchar(failureMessage)>0," - ",""),"Failed to call expression after ",attempts," attempt(s)",sep="")
MyLibrary.Sys.Log.Error(failureMessage,msg)
}
test <- function(FUN) withCallingHandlers(
expr=FUN(),
error=function(e) cat("ERROR CAUGHT\n"),
warning=function(w) {cat('WARNING CAUGHT\n'); invokeRestart(findRestart('muffleWarning'))}
)