R 使い方 debug(デバッグ)方法 スクリプトの書き方
バイオインフォ道場、くまぞうです。
スクリプトが思ったように動かない、そんなときはバグ(プログラムの間違い)があると言われます。スクリプトを書く場合、そのような間違いを書かないように注意することは当然ですが、完全に防ぐのは難しいことです。
スクリプトが思うように動かない場合は、debug作業(デバッグ:バグを取り除く)を行います。スクリプト言語やプログラム言語には、debug(デバッグ)作業をするための仕組みが準備されていることが多いです。Rの debug (デバッグ)機能を活用しましょう。
バグ と debug(デバッグ)
debug(デバッグ)とは、プログラムやスクリプトの間違いを発見し、手直しすることです。Rに限らず、プログラム言語やスクリプト言語について、共通して使われる用語です。「バグ」が間違いを指し、「debug(デバッグ)」が手直し作業を指します。
[browser-shot url=”https://goo.gl/To7a6B” target=”_blank” width=”600″]
一般的なデバッグ手法
debug(デバッグ)の基本は、データの表示です。変数表示や制御がどのように分岐したかを目印(関数名や処理の分岐点)で表示したりします。パフォーマンスへの影響が小さければ、これらの情報をログファイルなどに残しておくと、バグ発生やそのデバッグの際に役に立つことがあります。どうしても処理は少し重くなるので、パフォーマンスを重視する場合は、デバッグ用のモードを準備するなどして影響を小さくする工夫が必要です。ログのサイズが大きくなると色々と問題が発生するので、リングバッファ形式などを検討したりします。
デバッグの専用機能(デバッガ)を使うと、実行中のプログラムを途中停止して動作を確認するなどの高度なデバッグを行うことができます。デバッガには代表的な機能がありますが、そのようなプログラム環境では、使い方や呼び方もだいたい共通しているようです。
機能 | 説明 |
---|---|
ブレークポイント | プログラムの任意の位置で実行中に停止します。停止位置における変数確認や、以降の処理をステップ実行につなげます。 |
ステップ実行 | プログラム停止位置から、プログラムを1ステップずつ実行し、変数確認や条件分岐の確認などを行います。 |
変数確認 | 変数の値を確認します。構造化されたデータも展開して確認できる場合が多いです。 |
Rのデバッグ方法
Rもデバッガ機能(バグブラウザ)を備えています。ブレークポイント・ステップ実行・変数確認を行うことができます。バグブラウザは、Rのスクリプトでbrowser()
関数を呼び出したとき起動します。図は、ブレークポイントで停止した状態です。
my_r.r(動作確認用のスクリプト)
#! /usr/bin/Rscript
printf <- function(...) cat(sprintf(...))
x <- 1
browser()
if ( x >= 2 ) {
printf("x >= %d\n", x)
} else {
printf("x < %d\n", x)
}
バグブラウザの操作
バグブラウザは、browser()
関数をブレークポイントとして、実行途中で停止した状態を作り出します。以下の操作が、バグブラウザで使う主なコマンドです。
コマンド | 内容 |
---|---|
Q | バグブラウザ終了。実行終了。 |
c | バグブラウザ終了。停止位置以降を実行。 |
n | ステップ実行。 |
バグブラウザでのデバッグ
簡単な例(my_r.r)でバグブラウザの動作確認します。
my_r.r(動作確認用のスクリプト)
#! /usr/bin/Rscript
printf <- function(...) cat(sprintf(...))
x <- 1
browser()
if ( x >= 2 ) {
printf("x >= %d\n", x)
} else {
printf("x < %d\n", x)
}
コマンドQ – 実行終了
バグブラウザとスクリプトが実行終了します。例えば、「バグが判明して修正作業にうつる」・「操作ミスで最初からやり直し」など、すぐにデバッグ作業を終了したいときに使います。
$ R # R起動 R> source("my_r.r") Browse[1]> Q # バグブラウザ起動(Q:実行終了) >
コマンドc – 停止位置以降を実行
ステップ実行でなく、処理を通常動作させます。例えば、「ブレイクポイントからステップ実行、バグの見当がついて値書き換えなどの仮処置実施、以降の動作を確認したい」場合などに使います。
$ R # R起動 R> source("my_r.r") Browse[1]> c # バグブラウザ起動(c:停止位置以降の実行) x < 1 >
コマンドn – ステップ実行
ブレイクポイントから、1ステップずつ実行します。例えば、「値を確認しつつ、分岐がどのように進むか?」を細かくチェックしたい場合などに使います。状況としては、大まかなバグの位置が確認できていて、1つずつ確認しながら追い詰めている状況です。
$ R # R起動 R> source("my_r.r") Browse[1]> n # バグブラウザ起動(n:ステップ実行) my_bug.r#8 の debug: printf("x < %d\n", x) Browse[2]> n x < 1 >
変数書き換え
実行中に値を書き換えることができます。以降のステップにはその値が反映されます。例えば、「今まさにバグの位置が判明し、正しい値へ変更するなどの仮処置を行って、以降の処理が正常動作するか?」と確認する場合などに使います。以降のデバッグの例では、値を変更し、処理の分岐が変わることを確認しています。
$ R # R起動 R> source("my_r.r") Browse[1]> ls() # オブジェクトを確認 [1] "printf" "x" Browse[1]> x # 変数xの値を確認 [1] 1 Browse[1]> x <- 2 # 変数xの値の書き換え Browse[1]> n # ステップ実行 my_bug.r#6 の debug: printf("x >= %d\n", x) # 分岐変化 Browse[2]> c x >= 2 >