web-dev-qa-db-ja.com

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

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

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

96
forkandwait

行番号はわかりませんが、呼び出しスタックのどこで障害が発生したかがわかります。これは非常に役立ちます。

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()関数でラップします。

41
Shane

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

12
Hugh Perkins

このサポートは、R 2.10以降で近々提供される予定です。 Duncan Murdochは2009年9月10日にr-develに findLineNumとsetBreapoint :について投稿しました。

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

これらは、コードにソース参照デバッグ情報があることに依存しています。これは、source()が読み取るコードのデフォルトですが、パッケージのデフォルトではありません。パッケージコードでソース参照を取得するには、環境変数_R_KEEP_PKG_SOURCE=yes_を設定するか、R内で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")
_

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

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

10

設定して

options(show.error.locations = TRUE)

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

6
TMS

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

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

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

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

  1. コマンドラインから呼び出していたメインスクリプトの先頭に次を配置しました。これにより、Rセッションのグローバルエラー処理オプションが設定されます。私のメインスクリプトはmyMainScript.Rと呼ばれていました。コード内のさまざまな行には、実行内容を説明するコメントがあります。基本的に、このオプションを使用すると、Rがstop()をトリガーするエラーを検出すると、ディレクトリ~/myUsername/directoryForDumpのすべてのアクティブな環境にわたって作業メモリのRData(* .rda)ダンプファイルを作成します。 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が実行されます。 myMainScript.Rの先頭に配置されたステップ1で指定されたコードスニペットは、非対話型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. 余暇は、load('~/path/to/errorDump.rda')を使用してerrorDump.rdaをインタラクティブなRセッションにロードできます。ロードしたら、debugger(errorDump)を呼び出して、アクティブな環境のメモリ内のすべてのRオブジェクトを参照します。詳細については、debugger()のRヘルプを参照してください。

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

3
bmosov01

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

0
den2042