エラーのRスクリプトの行番号?


105

コマンドラインから長いRスクリプト(R --slave script.R)を実行している場合、エラー時に行番号を取得するにはどうすればよいですか?

可能な限り、スクリプトにデバッグコマンドを追加したくありません。Rを他のほとんどのスクリプト言語のように動作させたいだけです...


31
更新はありますか?四4年後、R.のすべての主流の採用にもかかわらずそれでも、問題と思われる
桂アンブロス

たくさんの小さな出力を持つ非常に長いRスクリプトもあり、Cのように(アンダースコア)(アンダースコア)LINE / FILE(アンダースコア)(アンダースコア)(行番号とスクリプト名)を印刷したいソースに。
mosh

Rが内部的に本当に「行番号」の概念を持っているかどうかはわかりません。ただし、これには完全なタスク、つまりトップレベルのタスクの概念があります。たとえば、失敗したトップレベルのタスクを通知するタスクハンドラーを簡単に定義できます。もちろん、それは大きなチェーンや大きな条件付きステートメントを持つ人々にとってはあまり快適ではありません。
russellpierce 2017年

回答:


45

これでは行番号はわかりませんが、コールスタックのどこでエラーが発生したかがわかり、非常に役立ちます。

traceback()

[編集:]コマンドラインからスクリプトを実行する場合、1つまたは2つの呼び出しをスキップする必要があります。インタラクティブおよび非インタラクティブRセッションについてはtraceback()を参照してください

私は通常のデバッグの容疑者なしでこれを行う別の方法を知りません:

  1. デバッグ()
  2. ブラウザ()
  3. options(error = recover)[これに戻すにはoptions(error = NULL)が続きます]

この関連記事をご覧ください。

[編集:]申し訳ありません...コマンドラインからこれを実行しているのを見ただけです。その場合、options(error)機能を使用することをお勧めします。以下に簡単な例を示します。

options(error = quote({dump.frames(to.file=TRUE); q()}))

エラー状態で必要なだけスクリプトを作成できるので、デバッグに必要な情報を決定するだけです。

それ以外の場合、気になる特定の領域がある場合(データベースへの接続など)、それらをtryCatch()関数でラップします。


最初の[Edit:]ブロックでリンクされているソリューションは私にとってはうまくいきます。最善のアプローチは、@ dshepherdのコメント、つまり追加のようですoptions(error=function() { traceback(2); if(!interactive()) quit("no", status = 1, runLast = FALSE) })(承認された回答のコメントを参照)。別のスレッドへのリンクを提供するだけでなく、ここで回答に追加するのが理にかなっていると思います。
cryo111 2018

1
LETはあなたがトレースバックに行番号を取得だと新しいオプションgithub.com/aryoda/tryCatchLog
lunguini

13

実行options(error=traceback)すると、エラーが発生するまでの行の内容について、もう少し情報が提供されます。エラーがある場合はトレースバックが表示され、一部のエラーでは行番号が先頭に付き#ます。しかし、それはヒットまたはミスであり、多くのエラーは行番号を取得しません。


2
私にとってはうまくいきません。ファイルが1つしかなく、行番号は表示されませんNo traceback available。エラーの後に表示されます。
Mark Lakata 2016年

11

このサポートは、R 2.10以降で予定されています。Duncan Murdochが2009年9月10日にfindLineNumおよびsetBreapointについてr-develに投稿したばかりです

デバッグを支援するために、R-develにいくつかの関数を追加しました。 findLineNum()どの関数のどの行がソースコードの特定の行に対応するかを見つけます。setBreakpoint()の出力を受け取り、そこにブレークポイントを設定するためのfindLineNum呼び出しtrace()を行います。

これらは、コードにソース参照デバッグ情報があることに依存しています。これはsource()、が読み取るコードのデフォルトですが、パッケージのデフォルトではありません。パッケージコードでソース参照を取得するには、環境変数を設定するR_KEEP_PKG_SOURCE=yesか、R内でsetを設定して options(keep.source.pkgs=TRUE)から、ソースコードからパッケージをインストールします。?findLineNum検索をグローバル環境に限定するのではなく、パッケージ内を検索するように指示する方法の詳細を読んでください。

例えば、

x <- " f <- function(a, b) {
             if (a > b)  {
                 a
             } else {
                 b
             }
         }"


eval(parse(text=x))  # Normally you'd use source() to read a file...

findLineNum("<text>#3")   # <text> is a dummy filename used by
parse(text=)

これは印刷されます

 f step 2,3,2 in <environment: R_GlobalEnv>

そしてあなたは使うことができます

setBreakpoint("<text>#3")

そこにブレークポイントを設定します。

コードにはまだいくつかの制限(そしておそらくバグ)があります。私はこれを修正します


ありがとう。r-develメーリングリストにも登録してください。私はそれが私の受信箱を詰まらせるであろうという仮定でr-helpを避けてきました(r-sig-financeはすでにそれをしています)。
シェーン

1
本当にRスクリプトでチャンスをうかがっせずにコマンドラインからどのようにこの作品を理解していない
ハーマンToothrot

1
@hirse:これはあなたの古い答えのほぼ10です。どうして私が引用しているふりをするために再フォーマットしたのですか?私はそうではなく、あなたの変化は私の意図を反映していませ
Dirk Eddelbuettel

「投稿されたダンカンマードック:」は引用のように聞こえますが、それが正しくない場合は編集を元に戻してください。自分が読みやすくするために、終了するまで日付を確認しませんでした。回答全体が古すぎる場合は、それを削除して将来の読者の混乱を取り除くこともできます。
hirse

元に戻せますか?ありがとうございました。
Dirk Eddelbuettel

6

あなたは設定することによってそれを行います

options(show.error.locations = TRUE)

この設定がRのデフォルトではないのはなぜですか。それは他のすべての言語であるので、そうあるべきです。


1
このオプションの背景情報については、stat.ethz.ch
R

1
これは以前は機能していましたが、信頼できないため無効にされました。私は、RStudioを強制的に使用させようとする試みだと思います。
Eric Leschinski 2017年

6
疑わしい。RコアとRStudioは非常に異なる組織であり、特にRコアは強力なオープンソースです。
ベンボルカー2017年

CentOSの6.9、R-3.4.2に従事
irritable_phd_syndrom

多分それは言及する価値があるでしょう、あなたはどんなコードを調達する前に、あなたは前もってオプションを設定するべきです。
JAponte

3

致命的ではないエラーを処理するためのグローバルRオプションを指定することは、エラーに関する情報を保持し、障害後にこの情報を調べるためのカスタマイズされたワークフローとともに、私にとってはうまくいきました。現在Rバージョン3.4.1を実行しています。以下に、私のために機能したワークフローの説明と、Rでグローバルエラー処理オプションを設定するために使用したいくつかのコードを含めました。

私が設定したように、エラー処理は、エラー発生時に作業メモリ内のすべてのオブジェクトを含むRDataファイルも作成します。このダンプはを使用してRに読み戻すload()ことができ、エラー発生時に存在していたさまざまな環境を、を使用してインタラクティブに検査できますdebugger(errorDump)

traceback()スタック内の任意のカスタム関数からの出力で行番号を取得できたことに注意します。ただし、スクリプトで使用される任意のカスタム関数をkeep.source=TRUE呼び出すときにオプションを使用した場合のみですsource()。このオプションがない場合、グローバルエラー処理オプションを以下のように設定すると、の完全な出力がtraceback()というエラーログに送信されますerror.logが、行番号は利用できませんでした。

ワークフローで行った一般的な手順と、非対話型Rの失敗後にメモリダンプとエラーログにアクセスする方法を次に示します。

  1. コマンドラインから呼び出すメインスクリプトの先頭に次のコードを追加しました。これにより、Rセッションのグローバルエラー処理オプションが設定されます。私のメインスクリプトはと呼ばれていましたmyMainScript.R。コードのさまざまな行の後には、その内容を説明するコメントがあります。基本的に、このオプションでは、Rがをトリガーするエラーに遭遇するstop()と、ディレクトリ内のすべてのアクティブな環境全体で作業メモリのRData(* .rda)ダンプファイルを作成し、いくつかの有用な情報を~/myUsername/directoryForDump含むエラーログをerror.log同じディレクトリ。このスニペットを変更して、エラーに対するその他の処理を追加できます(たとえば、ダンプファイルにタイムスタンプを追加したり、エラーログファイル名を追加したりできます)。

    options(error = quote({
      setwd('~/myUsername/directoryForDump'); # Set working directory where you want the dump to go, since dump.frames() doesn't seem to accept absolute file paths.
      dump.frames("errorDump", to.file=TRUE, include.GlobalEnv=TRUE); # First dump to file; this dump is not accessible by the R session.
      sink(file="error.log"); # Specify sink file to redirect all output.
      dump.frames(); # Dump again to be able to retrieve error message and write to error log; this dump is accessible by the R session since not dumped to file.
      cat(attr(last.dump,"error.message")); # Print error message to file, along with simplified stack trace.
      cat('\nTraceback:');
      cat('\n');
      traceback(2); # Print full traceback of function calls with all parameters. The 2 passed to traceback omits the outermost two function calls.
      sink();
      q()}))
  2. メインスクリプトと後続の関数呼び出しから、関数がソースされるときはいつでも、オプションkeep.source=TRUEが使用されていることを確認してください。つまり、関数をソースするには、を使用しますsource('~/path/to/myFunction.R', keep.source=TRUE)。これは、traceback()出力に行番号を含めるために必要です。を使用してこのオプションをグローバルに設定することもできるようですがoptions( keep.source=TRUE )、動作するかどうかを確認するためのテストは行っていません。行番号が必要ない場合は、このオプションを省略できます。

  3. ターミナル(Rの外部)から、を使用してメインスクリプトをバッチモードで呼び出しますRscript myMainScript.R。これにより、新しい非インタラクティブRセッションが開始され、スクリプトが実行されますmyMainScript.R。上部に配置されている手順1のコードスニペットmyMainScript.Rは、非インタラクティブRセッションのエラー処理オプションを設定します。
  4. の実行中にエラーが発生しましたmyMainScript.R。これはメインスクリプト自体にあるか、いくつかの関数がネストされています。エラーが発生すると、手順1で指定されたように処理が実行され、Rセッションが終了します。
  5. errorDump.rdaおよびという名前のRDataダンプファイルが、グローバルエラー処理オプション設定でerror.log指定されたディレクトリに作成され'~/myUsername/directoryForDump'ます。
  6. 暇なときにerror.log、エラーメッセージ自体やエラーの原因となった完全なスタックトレースなど、エラーに関する情報を確認してください。エラー時に生成されるログの例を次に示します。#文字の後の数字は、呼び出しスタックのさまざまなポイントでのエラーの行番号です。

    Error in callNonExistFunc() : could not find function "callNonExistFunc"
    Calls: test_multi_commodity_flow_cmd -> getExtendedConfigDF -> extendConfigDF
    
    Traceback:
    3: extendConfigDF(info_df, data_dir = user_dir, dlevel = dlevel) at test_multi_commodity_flow.R#304
    2: getExtendedConfigDF(config_file_path, out_dir, dlevel) at test_multi_commodity_flow.R#352
    1: test_multi_commodity_flow_cmd(config_file_path = config_file_path, 
    spot_file_path = spot_file_path, forward_file_path = forward_file_path, 
    data_dir = "../", user_dir = "Output", sim_type = "spot", 
    sim_scheme = "shape", sim_gran = "hourly", sim_adjust = "raw", 
    nsim = 5, start_date = "2017-07-01", end_date = "2017-12-31", 
    compute_averages = opt$compute_averages, compute_shapes = opt$compute_shapes, 
    overwrite = opt$overwrite, nmonths = opt$nmonths, forward_regime = opt$fregime, 
    ltfv_ratio = opt$ltfv_ratio, method = opt$method, dlevel = 0)
  7. 暇なときに、errorDump.rdaを使用してインタラクティブなRセッションに読み込むことができますload('~/path/to/errorDump.rda')。ロードされたら、呼び出しdebugger(errorDump)て、アクティブな環境のいずれかでメモリ内のすべてのRオブジェクトを参照します。詳細については、Rのヘルプを参照してdebugger()ください。

このワークフローは、コマンドラインで非インタラクティブRセッションが開始されていて、予期しないエラーに関する情報を保持したい、ある種の運用環境でRを実行する場合に非常に役立ちます。エラー発生時にワーキングメモリを検査するために使用できるファイルにメモリをダンプする機能と、コールスタックにエラーの行番号を含めることにより、エラーの原因を迅速に事後的にデバッグできます。


0

最初にoptions(show.error.locations = TRUE)、次にtraceback()。エラー行番号は#の後に表示されます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.