ブレーク/終了スクリプト


87

私はいくつかのデータ分析を行い、数百行の長さのプログラムを持っています。

プログラムの非常に早い段階で、品質管理を行いたいのですが、十分なデータがない場合は、プログラムを終了してRコンソールに戻したいと思います。それ以外の場合は、残りのコードを実行します。

私が試したbreakbrowserと、quitそれらのどれもがプログラムの残りの部分の実行を停止していない(とquit私は起こるしたいものではありませんだけでなく、完全にやめるR、として実行を停止します)。私の最後の手段はif-else、以下のようなステートメントを作成することです。

 if(n < 500){}
 else{*insert rest of program here*}

しかし、それは悪いコーディング慣行のようです。私は何かが足りないのですか?


4
quitプログラムの残りの部分の実行を確実に停止します。再現可能な例を提供してください。
Joshua Ulrich

@ JakeBurkhead-上記のコード(空のifステートメントを含む)が最善の方法ですか?@Joshua Ulrich、quitRをすべて終了しますが、プログラムを開いたままにする必要があるため、Rコンソールに戻りたいと思います。
user2588829 2013

プログラムとはどういう意味ですか?作成した関数を実行しているのですか、それともスクリプトで調達しているのですか?
Gavin Simpson

if-elseは、おそらくこれを処理する正しい方法です。例外は、すべてが正しく使用されている場合に発生してはならない状況です。それが発生する可能性があり、それを処理する方法を知っている場合は、通常の制御フローを使用してください。
マシュー

回答:


62

stopifnot()プログラムでエラーを生成したい場合は、この関数を使用できます。

foo <- function(x) {
    stopifnot(x > 500)
    # rest of program
}

+1!関数fooはスクリプトの先頭と呼ばれ、他の検証コントロールが含まれている必要があると思います...
agstudy 2013

22
stopifnotは便利ですが、を使用して細工された応答if(x < 500) { stop("Not enough observations in 'x': n < 500")}が望ましい場合があります。また、これがバッチジョブの場合は、エラースローせずに問題処理すると便利です。
Gavin Simpson

4
OPを混乱させようとするのはやめましょう。彼が望んでいるのは、stopifnot()ではなくquit()またはstop()です。
stackoverflowuser2010 2014

10
@ stackoverflowuser2010彼は望んでいないquit(質問を参照してください!)私も考えていないstopstopifnotこれを処理するための最良の方法です。stopエラーをスローすると、スクリプト全体が中止されます。一方でstopifnot(またはstop)回答OPが正常に終了する関数を書いて、最高の気に入ったように思わ、エラーなしで、状況の広い範囲で、より有益です。大規模なデータ分析ジョブ用に長時間実行されるスクリプトを多数作成したため、問題を処理してクリーンに返す代わりにエラーをスローする関数ほど煩わしいものはありません。しかし、明らかに私は何について話しているのかわかりません...
Gavin Simpson

@GavinSimpsonでエラーをスローすることについてのコメントを明確にしていただけますか?試してみるstop("my message")と、端末に印刷されError: "my message" Execution haltedます。これはエラーメッセージの出力を示していますが、エラーを「スロー」しないと言っていますか?(つまり、呼び出すスクリプトのいずれかがエラーをスローした場合に中止するように設定されているバッチジョブを停止しません)。ありがとう!(今私はRscriptでスクリプトを呼び出しています)
RRR

14

きれいではありませんが、exit()これが私のために働くRでコマンドを実装する方法です。

exit <- function() {
  .Internal(.invokeRestart(list(NULL, NULL), NULL))
}

print("this is the last message")
exit()
print("you should not see this")

軽くテストしただけですが、これを実行するthis is the last messageと、エラーメッセージが表示されずにスクリプトが中止されます。


欠点は、CRANパッケージのコードでは許可されないことです。したがって、CRANにアップロードするパッケージで使用する場合は、に警告が表示されますR CMD CHECK
MS Berends 2017年

1
はい、これはシステム機能のように見えます。インタプリタの内部の詳細が変更されると壊れてしまう可能性があるので、個別のパッケージではなく、Rコアの一部である方がよいでしょうか?これは、Rソースコードのさまざまなパスをたどって、エラーメッセージが表示されずにインタープリターを終了する正しい場所にたどり着く方法を確認することでわかりました。そこにたどり着く方法はそれほど多くありませんでした。これが私が使用する理由で.invokeRestartあり、次にそれが必要であるように思われます.Internal
jochen 2017年

そうそう、CRANポリシー以外は、素晴らしい解決策だと思います。+10担当者をお届けします;)
MS Berends 2017年

変だ。私はこれを試しましたが、最後の出力行は[1]「これは表示されないはずです」Rバージョン3.4.3(2017-11-30)プラットフォーム:x86_64-pc-linux-gnu(64ビット)実行中:Red Hat Enterprise Linux Serverリリース6.10(Santiago)
CodingMatters 2018

2
私はそれを動作させることができましたexit <- function() { invokeRestart("abort") }
ドロップレット

12

if-else構造を逆にします。

if(n >= 500) {
  # do stuff
}
# no need for else

2
十分に単純で、これが私にできる最善の方法だと思います。ありがとう
user2588829 2013

9

編集: OPが長いスクリプトを実行しているようです。その場合、品質管理のにスクリプトの一部をラップするだけで済みます。

if (n >= 500) {

.... long running code here

}

関数から抜け出す場合は、return()明示的または暗黙的に、が必要になる可能性があります。

たとえば、明示的なダブルリターン

foo <- function(x) {
  if(x < 10) {
    return(NA)
  } else {
    xx <- seq_len(x)
    xx <- cumsum(xx)
  }
  xx ## return(xx) is implied here
}

> foo(5)
[1] 0
> foo(10)
 [1]  1  3  6 10 15 21 28 36 45 55

return()暗示されている、私はあなたが行ってしたいかのように最後の行があることを意味しreturn(xx)、それはへの呼び出しをオフに残すために、わずかに、より効率的ですreturn()

複数の返品の悪いスタイルを使用することを検討する人もいます。長い関数では、関数がどこで終了するかを追跡することが困難になったり、エラーが発生しやすくなる可能性があります。したがって、代替手段は単一の戻り点を持つことですが、if () else ()句を使用して戻りオブジェクトを変更します。そのような変更foo()

foo <- function(x) {
  ## out is NA or cumsum(xx) depending on x
  out <- if(x < 10) {
    NA
  } else {
    xx <- seq_len(x)
    cumsum(xx)
  }
  out ## return(out) is implied here
}

> foo(5)
[1] NA
> foo(10)
 [1]  1  3  6 10 15 21 28 36 45 55

私もこれを考えましたが、OPが機能から抜け出すことについて話しているのかどうかは明らかではありません。
トーマス

ええ、トーマスは正しいです-私は機能から抜け出すことについて話していません。
user2588829 2013

1
@ user2588829 100行以上のスクリプトではなく、Rの関数として配置する方がはるかに良いでしょう。
Gavin Simpson

@GavinSimpsonああ、私はまだRに慣れていないので、それを知りませんでした。私がそれを100以上のライン関数として定義する場合、それはより良い習慣ですか?
user2588829 2013

1
@ user2588829はい、はるかに優れています。関数の引数を制御して、必要なものを渡すことができるようにします。また、100行以上のコードを調達して分析を実行する代わりに、実行するだけですmyFun(arg1, arg2, arg3)。これは、物事を整理するためのはるかに優れた方法です。
Gavin Simpson

9

おそらく、ある時点で長いスクリプトの実行を停止したいだけです。すなわち。CまたはPythonでexit()をハードコーディングしたいように。

print("this is the last message")
stop()
print("you should not see this")

1
このコードでは、エラーメッセージが表示されますError in eval(expr, envir, enclos) :
jochen 2017年

2
はい、実行は実際に停止します。偶然にも、またはに置き換えるstop()と、スクリプトも停止します(もちろんエラーメッセージのみが異なります)。exit()please.stop.now()
jochen 2017年

1
@jochenstop()コマンド内に引用句を追加すると、この「エラー」を他のメッセージと区別するのに役立ちます。例:単独stop("Manual break inserted here")よりも有益な場合がありますstop()
OmarWasow20年

3

これは古い質問ですが、まだ明確な解決策はありません。これはおそらくこの特定の質問に答えているわけではありませんが、「Rスクリプトを正常に終了する方法」に関する答えを探している人はおそらくここにたどり着きます。R開発者はexit()関数の実装を忘れたようです。とにかく、私が見つけたトリックは次のとおりです。

continue <- TRUE

tryCatch({
     # You do something here that needs to exit gracefully without error.
     ...

     # We now say bye-bye         
     stop("exit")

}, error = function(e) {
    if (e$message != "exit") {
        # Your error message goes here. E.g.
        stop(e)
    }

    continue <<-FALSE
})

if (continue) {
     # Your code continues here
     ...
}

cat("done.\n")

基本的に、フラグを使用して、指定されたコードブロックの継続かどうかを示します。次に、stop()関数を使用して、カスタマイズされたメッセージをtryCatch()関数のエラーハンドラーに渡します。エラーハンドラがメッセージを受信して​​正常に終了する場合、エラーハンドラはエラーを無視し、継続フラグをに設定しFALSEます。


0

「tools」パッケージのpskill関数を使用してR、現在のプロセスを中断し、コンソールに戻ることができます。具体的には、各スクリプトの冒頭で入手したスタートアップファイルに次の関数を定義しています。ただし、コードの先頭で直接コピーすることもできます。次にhalt()、コードの任意の場所に挿入して、スクリプトの実行をその場で停止します。この関数はGNU / Linuxでうまく機能し、Rドキュメントから判断すると、Windowsでも機能するはずです(ただし、確認しませんでした)。

# halt: interrupts the current R process; a short iddle time prevents R from
# outputting further results before the SIGINT (= Ctrl-C) signal is received 
halt <- function(hint = "Process stopped.\n") {
    writeLines(hint)
    require(tools, quietly = TRUE)
    processId <- Sys.getpid() 
    pskill(processId, SIGINT)
    iddleTime <- 1.00
    Sys.sleep(iddleTime)
}

> pskill(processId、SIGINT)はセッションを閉じ、ユーザーをRStudioから追い出します。かなり危険ですが機能的です。
Espanta

RStudioがクラッシュすることを知りませんでしたが、同じ問題が次の場所で説明されています:stackoverflow.com/questions/32820534/…Linuxでは、私のソリューションは正常に機能します。stopifnotに対するその利点は、stopifnot()エラーメッセージが表示されないことです。
フランソワトノー

私はWindowsをチェックしました、そしてそれは狂ったように振る舞います。とにかくありがとう。私はそのスキルが好きです。
エスパンタ2016年

0

ここに:

if(n < 500)
{
    # quit()
    # or 
    # stop("this is some message")
}
else
{
    *insert rest of program here*
}

両方ともquit()stop(message)スクリプトを終了します。Rコマンドプロンプトからスクリプトを取得している場合は、Rquit()も終了します。


7
すでに投稿されている回答と重複する回答を投稿することはお勧めできません。
トーマス

@Thomasこれはどの答えを複製しますか?停止と終了の両方を使用して、実際にそれらの違いを説明しているこの答えだけが表示されます。

@トーマス:私の答えが重複する答えを正確に説明してください。
stackoverflowuser2010 2015年

@トーマス:あなたの批判について質問しました。お返事をお待ちしております。
stackoverflowuser2010 2017年

5
@ netskinkの答えの用途stop()、およびOPはすでに、彼らが望んでいないことをコメントで示されたquit()...
ベンBolker
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.