10

エラーと警告の両方をスローする関数を扱っています。 (関連:警告についての警告)

多くの場合、警告によってエラーが発生します。このような状況では、警告を無視してエラーのみを処理したいと考えています。

一方、警告のみ (エラーなし) の場合は、警告をキャッチしたいと考えています。

私は悪名高い使いやすい で作業しようとしていますtryCatch

私の差し迫った質問は次のとおりです: s の前にs を強制的tryCatchに処理する方法はありますか (または、エラーが発生したときに警告を無視する方法はありますか)?errorwarning

ドキュメントからの私の理解で?tryCatchは、条件は FIFO で処理されます。その場合、私の当面の質問に対する答えはいいえです - 少なくとも直接ではありません。その場合、警告を処理し、エラーをキャッチしながら関数を続行することは可能ですか?

私には利用できない解決策:

  • suppressWarnings# それでも警告をキャッチして処理したい
  • options(warn=2) # 特定の警告は無害です
     relevant from `?tryCatch`

expr の評価中に条件が通知された場合、確立されたハンドラーがチェックされ、最近確立されたハンドラーから始めて、条件のクラスに一致するハンドラーが検出されます。1 つの tryCatch で複数のハンドラーが指定されている場合、最初のハンドラーが 2 番目のハンドラーよりも新しいと見なされます。ハンドラーが見つかった場合、ハンドラーを確立した tryCatch 呼び出しに制御が移され、ハンドラーが検出され、それ以降のすべてのハンドラーが確立されなくなります。ハンドラーは条件を引数として呼び出され、ハンドラーによって返される結果は次のように返されます。 tryCatch 呼び出しの値。

以下はおもちゃの例です。

F.errorAndWarning <- function() {
    warning("Warning before the error")
    cat("I have moved on.")
    stop("error")
    TRUE
}
F.error <- function() {stop("error"); TRUE}


test <- function(F)
  tryCatch(expr= {F}()
          , error=function(e)   cat("ERROR CAUGHT")
          , warning=function(w) cat("WARNING CAUGHT")
          )

test(F.error)
# ERROR CAUGHT
test(F.errorAndWarning)
# WARNING CAUGHT

期待/理想的な出力:

test(F.errorAndWarning)
# ERROR CAUGHT
4

4 に答える 4

9

これは、「警告を処理し、エラーをキャッチしながら関数を続行することは可能ですか?」に関連しています。質問。

同様の問題があり、警告とエラーのログ機能を 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)
}
于 2013-10-18T10:05:09.800 に答える
5

expressionエラーを実行して優先順位を付ける関数を作成します。

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
于 2013-10-17T18:45:06.963 に答える
4

呼び出しで返された生の R オブジェクトと共に、すべての警告、エラー、および標準出力に出力されたものをキャプチャする、 panderパッケージでの評価用の便利なヘルパー関数を作成しました。

> 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"
于 2013-10-17T18:19:43.810 に答える