2020年12月15日火曜日

Python の logging で JSON 内にある日本語を表示するテクニック

概要

JSON のバリュー側に日本語があるとうまく表示されないケースがあります
json モジュールを使って dict - string の変換をうまく行う必要があります

環境

  • macOS 10.15.7
  • Python 3.8.5

通常の logger の場合

# -*- coding: utf-8 -*-
import logging
import json

logging.basicConfig(level = logging.DEBUG)
logger = logging.getLogger(__name__)

d = '{"msg":"こんにちわ"}'
dd = json.loads(d)

logger.info(d) # ちゃんと日本語が表示される
logger.info(type(d))

logger.info(dd)
logger.info(dd["msg"]) # ちゃんと日本語が表示される
logger.info(type(dd))

logger.info(json.dumps(dd))
logger.info(json.dumps(dd, ensure_ascii=False)) # ちゃんと日本語が表示される


まず日本語の JSON 文字列を json.loads で dict に変換する場合は冒頭のマジックコメントが必要です
これがないと SyntaxError: Non-ASCII character '\xe3' のエラーになります

logger を使った場合に正常に表示されるパターンは 3 種類で


* 日本語を含む文字列の JSON をそのまま logger.info した場合
* dict に変換後日本語のバリューに直接アクセスした場合
* json.dumps で ensure_ascii=False を指定して dict を文字列に戻した場合

になります
特に最後の ensure_ascii=False が重要で一度 json.loads で dict に変換した場合内部的には unicode で扱われているので普通に戻しても unicode で戻ってしまうので注意しましょう

python-json-logger を使う方法

過去に紹介した python-json-logger を使った場合には以下のようになります

import logging
from flask import Flask
from pythonjsonlogger import jsonlogger

app = Flask(__name__)

handler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter(json_ensure_ascii=False)
handler.setFormatter(formatter)
logging.getLogger().addHandler(handler)

@app.route("/")
def index():
    app.logger.setLevel(logging.INFO)
    app.logger.info("��スシ")
    return 'ok'

ちゃんと json_ensure_ascii のオプションを指定できるようにしてくれているのでこれに False を指定すれば OK です

参考サイト

0 件のコメント:

コメントを投稿