概要
Pythonのプログラムでloguruを使っていたら以下のエラーに。
RuntimeError: Could not acquire internal lock because it was already in use (deadlock avoided). This likely happened because the logger was re-used inside a sink, a signal handler or a 'del' method. This is not permitted because the logger and its handlers are not re-entrant.
原因
エラーメッセージから、「ロガー自身の内部処理中に再帰的に呼び出していること」が原因であることが分かります。
どこに問題があったのだろうとコードを見ていると、ロガー内部の処理で再びロガーを呼び出してしまっていました。
from loguru import logger
logger.remove()
def json_formatter(message) -> None:
record = message.record
log_data = {
"timestamp": record["time"].isoformat(),
"level": record["level"].name,
"message": record["message"],
#### 省略 ####
}
logger.debug(json.dumps(log_data, ensure_ascii=False))
logger.add(
json_formatter,
level="DEBUG"
)
この場合、ロガーが自分自身を再帰的に呼び出すことになり、デッドロック回避のエラーが発生するのです。
解決方法
ロガーの出力の中でlogger.debugを使うとロガー自身を呼び出してしまうので、
printなどを使うとエラーがなくなります。
from loguru import logger
logger.remove()
def json_formatter(message) -> None:
record = message.record
log_data = {
"timestamp": record["time"].isoformat(),
"level": record["level"].name,
"message": record["message"],
#### 省略 ####
}
print(json.dumps(log_data, ensure_ascii=False)) # printに変更
logger.add(
json_formatter,
level="DEBUG"
)
参考
ちなみに、loguruは、Pythonの人気ロギングライブラリの一つで、
標準のloggingよりもシンプルに設定できることなどが特徴です。
(loggingはハンドラやフォーマッタなどの設定が必要)
logger.add()で出力先(シンク)を柔軟に追加でき、上記の例で言えばjson_formatterというカスタムシンクを設定してます。しかしそのシンク内での再帰的なロギングをloguruは禁止している、ということですね。