Rで解析:コンソールとログファイルの両方に記録を残せる「logr」パッケージの紹介
「logr」パッケージは、コンソールへの表示とログファイルへの書き出しを同時に行うコマンド群を提供し、実行したコードや出力したメッセージ、警告やエラーをひとつのログファイルへ時刻付きでまとめて残せます。渡すのは文字列のメッセージや、データフレームなどコンソールに表示できるRオブジェクトです。処理の途中経過や異常終了の原因をあとから追いたい人に向いているのではないかと考えます。
パッケージバージョンは1.4.0。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。
<おすすめのRに関する書籍です>
パッケージのインストール
下記コマンドを実行してください。
# パッケージのインストール
install.packages("logr")
# パッケージの読み込み
library("logr")
Loading required package: commonコマンド例
詳細はコメント、パッケージのヘルプを確認してください。
「logr」パッケージでは、log_open()で開いたログファイルの情報がセッション内に保持されるため、以降のコマンドへファイルの参照を渡し直す必要はありません。log_print()やlog_warning()などのコマンドは、コンソールへの表示とログファイルへの書き込みを同時に行い、log_close()を呼ぶまでその状態が続きます。
以降の例では、京都府南部の茶業地域を想定した、産地別の収穫量の記録を共通のデータとして使い回します。
# 京都府南部の茶業地域を想定した、産地別収穫量の記録
chagyo <- data.frame(
産地 = c("宇治市", "和束町", "宇治田原町", "南山城村", "笠置町"),
収穫量kg = c(1280, 2140, 1860, 640, 540),
品種 = c("やぶきた", "さみどり", "やぶきた", "おくみどり", "やぶきた"),
stringsAsFactors = FALSE
)ログを開く:log_openコマンド
log_open()は新しいログファイルを開き、以降log_close()を呼ぶまでの書き込み先として保持します。file_nameに拡張子まで指定するとそのままファイル名になり、logdirをFALSEにすると”log”ディレクトリを作らずに指定した場所へ直接保存します。ヘッダーや注記が不要な場合は、headerとshow_notesをそれぞれFALSEにします。
| オプション | 意味 | 初期値 |
|---|---|---|
| file_name | ログファイルの名前(拡張子や保存先のパスを含めてもよい)。省略するとプログラムファイルの名前が使われる | “” |
| logdir | TRUEにすると”log”という名前のログ用ディレクトリを自動作成してそこに保存する。FALSEならfile_nameで指定した場所にそのまま保存する | TRUE |
| show_notes | ログにNOTE(注記)を書き込むかどうか | TRUE |
| autolog | dplyr・tidyr・sassy系列のコマンドの実行を自動でログに記録する機能を使うかどうか | NULL |
| compact | TRUEにすると余分な空行を減らし、ログを詰めて出力する | FALSE |
| traceback | エラー発生時にトレースバックをログへ書き込むかどうか | TRUE |
| header | ログの冒頭に、保存先やRのバージョンなどをまとめたヘッダーを書き込むかどうか | TRUE |
| stdout | TRUEにするとログをファイルではなく標準出力へ書き出す | FALSE |
| line_size | 1行あたりの最大文字数。超えた行は折り返される | 80 |
# ログの保存先ディレクトリを作成
log_dir <- file.path(tempdir(), "chagyo_log")
dir.create(log_dir, showWarnings = FALSE)
# ヘッダーと注記を省いて、産地別収穫量のログを開く
log_open(file.path(log_dir, "chagyo.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo.log"
# 開始のメッセージをログに残す
log_print("宇治茶生産ログを開始します")
宇治茶生産ログを開始します
# ログを閉じる(フッターも省く)
log_close(footer = FALSE)
<おすすめのRに関する書籍です>
現在のプログラムコードの記録:log_codeコマンド
log_code()は、呼び出された時点で実行中のプログラム(スクリプトファイル)のソースコードをそのままログへ書き写します。ログの内容だけを見て、どの処理がどんな出力を生んだのかをあとから追えるようにするためのコマンドで、オプションはありません。コンソールに直接打ち込んだ場合ではなく、ファイルとして保存したスクリプトを実行した場合に有効です。
# ログを開く
log_open(file.path(log_dir, "chagyo_code.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_code.log"
# このスクリプトのソースコードをログに書き写す
log_code()
[1] TRUE
# ログを閉じる
log_close(footer = FALSE)
<おすすめのRに関する書籍です>
警告メッセージの記録:log_warningコマンド
log_warning(msg)は、指定した文字列を警告としてログに書き込むと同時に、通常のwarning()と同じように呼び出し元へ警告を送出します。処理は続けられるが確認しておきたい状態に気づいたときに、その理由をログへ残すためのコマンドです。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | ログに書き込む警告メッセージ | NULL |
# ログを開く
log_open(file.path(log_dir, "chagyo_warning.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_warning.log"
# 収穫量が600kgを下回る産地を確認
low_yield <- chagyo$産地[chagyo$収穫量kg < 600]
# 該当する産地があれば警告を記録
for (sanchi in low_yield) {
log_warning(paste0(sanchi, "の収穫量が600kgを下回っています"))
}
Warning: 笠置町の収穫量が600kgを下回っています
# ログを閉じる
log_close(footer = FALSE)記録した警告の取得:get_warningsコマンド
get_warnings()は、log_open()からlog_close()までの間にlog_warning()で記録した警告メッセージを、文字列ベクトルとしてまとめて取得します。ログを閉じたあとに呼び出しても、直前のセッションで記録した警告を参照できます。オプションはありません。
# ログを開く
log_open(file.path(log_dir, "chagyo_getwarnings.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_getwarnings.log"
# 収穫量が少ない産地の警告を記録
for (sanchi in low_yield) {
log_warning(paste0(sanchi, "の収穫量が少なくなっています"))
}
Warning: 笠置町の収穫量が少なくなっています
# ログを閉じる
log_close(footer = FALSE)
# 記録した警告をまとめて取得
get_warnings()
[1] "Warning: 笠置町の収穫量が少なくなっています"エラーメッセージの記録:log_errorコマンド
log_error(msg)は、指定した文字列をエラーとしてログに書き込みます。呼び出すとログがその場で自動的に閉じられるため、このあとであらためてlog_close()を呼ぶ必要はありません。stop()のように処理そのものを打ち切るわけではなく、後続のコードはそのまま実行されます。
| オプション | 意味 | 初期値 |
|---|---|---|
| msg | ログに書き込むエラーメッセージ | NULL |
# 品種が未記入の出荷記録
shipment <- data.frame(産地 = "笠置町", 収穫量kg = 320, 品種 = NA, stringsAsFactors = FALSE)
# ログを開く
log_open(file.path(log_dir, "chagyo_error.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_error.log"
# 品種が未記入ならエラーとして記録する
if (is.na(shipment$品種)) {
log_error("品種が未記入の出荷記録があります")
}
Error: 品種が未記入の出荷記録があります
Error: 品種が未記入の出荷記録がありますログの状態確認:log_statusコマンド
log_status()は、ログが開いているか閉じているかを”open”または”closed”の文字列で返します。オプションはありません。
# ログを開く前の状態を確認
log_status()
[1] "closed"
# ログを開く
log_open(file.path(log_dir, "chagyo_status.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_status.log"
# ログを開いた後の状態を確認
log_status()
[1] "open"
# ログを閉じる
log_close(footer = FALSE)
# ログを閉じた後の状態を確認
log_status()
[1] "closed"ログの一時停止:log_suspendコマンド
log_suspend()は、ログファイルへの書き込みだけを一時的に止めます。停止中もlog_print()などのコマンドはコンソールへの表示は続けますが、ログファイルには書き込まれません。log_resume(file_name)を呼ぶと、指定したログファイルへの書き込みを再開します。
# ログを開く
lf <- log_open(file.path(log_dir, "chagyo_suspend.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
# 一時停止前のメッセージ
log_print("一時停止前のメッセージ")
一時停止前のメッセージ
# ログへの書き込みを一時停止
log_suspend()
Log suspended
# 停止中はコンソールに表示されてもログには残らない
log_print("停止中は記録されないメッセージ")
[1] "停止中は記録されないメッセージ"
# ログへの書き込みを再開
log_resume(lf)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_suspend.log"
# 再開後のメッセージ
log_print("再開後のメッセージ")
再開後のメッセージ
# ログを閉じる
log_close(footer = FALSE)現在のログファイルのパス取得:log_pathコマンド
log_path()は、現在開いているログファイルのフルパスを返します。オプションはありません。
# ログを開く
log_open(file.path(log_dir, "chagyo_path.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_path.log"
# 現在のログファイル名を確認
basename(log_path())
[1] "chagyo_path.log"
# ログを閉じる
log_close(footer = FALSE)ログの終了処理:log_closeコマンド
log_close(footer)は、開いているログファイルを閉じます。footerをTRUEにすると、終了時刻や処理にかかった時間をログの末尾に書き込みます。
| オプション | 意味 | 初期値 |
|---|---|---|
| footer | ログの末尾に、終了時刻や処理にかかった時間をまとめたフッターを書き込むかどうか | TRUE |
# ログを開く
log_open(file.path(log_dir, "chagyo_footer.log"), logdir = FALSE, header = FALSE, show_notes = FALSE)
[1] "C:\\Users\\chalu\\AppData\\Local\\Temp\\Rtmpc78VH1/chagyo_log/chagyo_footer.log"
# 記録するメッセージ
log_print("フッターありで閉じる")
フッターありで閉じる
# 終了時刻を書き込んでログを閉じる
log_close(footer = TRUE)
<おすすめのRに関する書籍です>
この記事が誰かの役に立ちますように。