31

たとえば、142個の小さなセクションの大きなRスクリプトがあります。1つのセクションがエラーで失敗した場合、スクリプトを停止するのではなく続行したいと思います。セクションは必ずしも相互に依存しているわけではありませんが、依存しているセクションもあります。真ん中の1つが失敗した場合、それは問題ありません。try()このスクリプトを呼び出しでこしょうしたくない。また、各セクションは非常に短いため、ファイルを多数の小さなファイルに分割する必要はありません。

source()Rコンソールにコピーして貼り付けたように動作させることができれば素晴らしいと思います。または、エラーを警告にダウングレードする方法があれば、それでも問題ありません。

スクリプトが実行されたら、エラーまたは警告テキストの出力をgrep(または同様)して、最初のエラーで停止しただけでなく、発生したすべてのエラーまたは警告を確認できるようにします。

?sourceStackOverflowの[R]タグを読んで検索しました。私は次の同様の質問を見つけましたがtrytryCatch提供された答えでした:

Rスクリプト-エラー時にコード実行を続行
する方法エラーメッセージを受信した後、実行を停止する代わりにRスクリプトを続行する方法はありますか?

私は上記の理由で探していtryません。tryCatchこれは、テストフレームワークを認識していて、多くのtry()またはtest_that()呼び出し(または同様のもの)が完全に適切であるRパッケージテスト用ではありません。これは、私が説明したようなスクリプトを持っている他の何かのためのものです。

ありがとう!

4

3 に答える 3

26

これをより具体的にするために、以下はどうでしょうか?

最初に、アプローチをテストするために、いくつかのステートメントを含むファイル ( と呼びます"script.R") を作成します。最初のステートメントは評価時にエラーをスローします。

## script.R

rnorm("a")
x <- 1:10
y <- 2*x

次に、それを式リストに解析し、各要素を順番に評価し、評価を の呼び出し内にラップして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
于 2013-01-30T19:55:56.157 に答える
15

evaluateパッケージは、その機能に別のオプションを提供しますevaluate()。私の他の提案ほど軽量ではありませんが、knitrを支える機能の 1 つとして、十分にテストされています。

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

コマンドラインで実際にステートメントを入力したように見える出力を得るには、 を使用しますreplay()。(ヒントをくれたハドリーに感謝):

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

編集

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
# > 
于 2013-01-30T20:42:40.790 に答える
5

これは不格好で、誰も友達を使用して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.
}
于 2013-01-30T20:03:10.760 に答える