エラーが発生した場合、Rにステートメントを数回再試行するように指示するにはどうすればよいですか?例えば。私は次のようなことをしたいと思っていました:
tryCatch(dbGetQuery(...), # Query database
error = function(e) {
if (is.locking.error(e)) # If database is momentarily locked
retry(times = 3) # retry dbGetQuery(...) 3 more times
else {
# Handle other errors
}
}
)
私は通常、try
ブロックをループに入れ、それ以上失敗しないか、最大試行回数に達したときにループを終了します。
some_function_that_may_fail <- function() {
if( runif(1) < .5 ) stop()
return(1)
}
r <- NULL
attempt <- 1
while( is.null(r) && attempt <= 3 ) {
attempt <- attempt + 1
try(
r <- some_function_that_may_fail()
)
}
私は、試行間の設定可能な待機を使用して、設定可能な回数だけ操作を簡単に再試行できるクイック関数を作成しました。
_library(futile.logger)
library(utils)
retry <- function(expr, isError=function(x) "try-error" %in% class(x), maxErrors=5, sleep=0) {
attempts = 0
retval = try(eval(expr))
while (isError(retval)) {
attempts = attempts + 1
if (attempts >= maxErrors) {
msg = sprintf("retry: too many retries [[%s]]", capture.output(str(retval)))
flog.fatal(msg)
stop(msg)
} else {
msg = sprintf("retry: error in attempt %i/%i [[%s]]", attempts, maxErrors,
capture.output(str(retval)))
flog.error(msg)
warning(msg)
}
if (sleep > 0) Sys.sleep(sleep)
retval = try(eval(expr))
}
return(retval)
}
_
したがって、val = retry(func_that_might_fail(param1, param2), maxErrors=10, sleep=2)
と書くだけで、それらのパラメーターを使用してその関数の呼び出しを再試行し、10個のエラーの後にあきらめて、試行の間に2秒スリープすることができます。
また、別の関数をパラメーターisError
として渡すことで、エラーの外観の意味を再定義できます。デフォルトでは、stop
で通知されたエラーをキャッチします。これは、呼び出されている関数がFALSE
やNULL
を返すなど、エラー時に何か他のことをする場合に役立ちます。
これは私がこれまでに見つけた代替手段であり、より明確で読みやすいコードが得られます。
お役に立てれば。
値を事前に割り当てず、for
の代わりにwhile
を使用しないソリューション:
some_function_that_may_fail <- function(i) {
if( runif(1) < .5 ) stop()
return(i)
}
for(i in 1:10){
try({
r <- some_function_that_may_fail(i)
break #break/exit the for-loop
}, silent = FALSE)
}
r
は、必要な試行回数と等しくなります。エラーの出力が不要な場合は、silent
をTRUE
に設定します
これは、応答するカスタム条件を生成する関数です
locked <- function(message="occurred", ...) {
cond <- simpleCondition(message, ...)
class(cond) <- c("locked", class(cond))
cond
}
(無限の)再起動を可能にするために実装された機能
f <- function() {
cnt <- 0L
repeat {
again <- FALSE
cnt <- cnt + 1L
withRestarts({
## do work here, and if needed...
signalCondition(locked())
}, retry=function() {
again <<- TRUE
})
if (!again) break
}
cnt
}
withCallingHandlers
条件を処理するためのtryCatch
の使用(locked
とは異なり、条件がアクティブであると通知されたコンテキストを維持するため)
withCallingHandlers({
n_tries <- 0L
f()
}, locked=function(e) {
n_tries <<- n_tries + 1L
if (n_retries < 3)
invokeRestart("retry")
})
オブジェクトを最初からエラーとして設定するのが好きです。接続に問題がある場合は、スリープ時間を追加するのに役立つこともあります。
res <- simpleError("Fake error to start")
counter <- 1
max_tries <- 10
# Sys.sleep(2*counter)
while(inherits(res, "error") & counter < max_tries) {
res <- tryCatch({ your_fun(...) },
error = function(e) e)
counter <- counter + 1
}