ログをJSONで取得したいため、JSON log formatterを使用したが、なぜか日本語(2バイト文字)が文字化けしてしまった。
環境
Windows10 Home 10.0.18362 ビルド 18362
Python 3.8.3
JSON-log-formatter 0.3.0
失敗例
以下のプログラムを実行する。
import logging
import json_log_formatter
formatter = json_log_formatter.JSONFormatter()
json_handler = logging.FileHandler(filename='my-log.json', encoding='utf-8')#UTF-8で出力する
json_handler.setFormatter(formatter)
logger = logging.getLogger('my_json')
logger.addHandler(json_handler)
logger.setLevel(logging.INFO)
logger.info('この文字列が文字化けする', extra={'extra': 'この文字列も文字化けする'})
出力されたログファイル「my-log.json」は次のようになる。(見やすいように整形)
{
"extra": "\u3053\u306e\u6587\u5b57\u5217\u3082\u6587\u5b57\u5316\u3051\u3059\u308b",
"message": "\u3053\u306e\u6587\u5b57\u5217\u304c\u6587\u5b57\u5316\u3051\u3059\u308b",
"time": "2020-10-21T02:29:53.275011"
}
extraとmessageが文字化けしている。
解決策
「json_log_formatter」ディレクトリ内の「__init__.py」の「to_json」メソッドを次のように書き換える。
def to_json(self, record):
"""Converts record dict to a JSON string.
It makes best effort to serialize a record (represents an object as a string)
instead of raising TypeError if json library supports default argument.
Note, ujson doesn't support it.
Override this method to change the way dict is converted to JSON.
"""
try:
#return self.json_lib.dumps(record, default=_json_serializable)#書き換え前
return self.json_lib.dumps(record, ensure_ascii=False, default=_json_serializable)#書き換え後
# ujson doesn't support default argument and raises TypeError.
except TypeError:
#return self.json_lib.dumps(record)#書き換え前
return self.json_lib.dumps(record, ensure_ascii=False)#書き換え後
辞書をJSON化するdumpsメソッドの引数に、ensure_ascii=Falseを付け加える。
再度「json_log_test.py」を実行し、出力ファイルを確認すると、今度は文字化けしていない。
{
"extra": "この文字列も文字化けする",
"message": "この文字列が文字化けする",
"time": "2020-10-21T02:31:16.704940"
}
参考サイト
Python の json.dumps() で日本語が文字化けする場合のメモ - 牌語備忘録 -pygo
https://cortyuming.hateblo.jp/entry/20140920/p2
JSON-log-formatter · PyPI
https://pypi.org/project/JSON-log-formatter/