1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python標準loggingをシンプルに使う

1
Last updated at Posted at 2026-09-05

背景

普段は loguru を使っているが、外部ライブラリを追加できない環境でPython標準ライブラリの logging を使いたい。

要件は以下。

  • コンソールとファイルの両方に出力
  • ログファイルは <root>/logs/yyyymmddThhmmss.log
  • root は呼び出し元から Path で渡す
  • ログディレクトリ名は引数で変更可能(デフォルトは "logs"
  • ファイルにはミリ秒まで記録
  • ミリ秒の区切りは . にする
  • コンソールではミリ秒を省略
  • loggingの設定は別ファイルにまとめる

構成

loggingの設定は logging_config.py に切り出す。

project/
├─ main.py
├─ logging_config.py
└─ logs/

logging_config.py

import logging
from datetime import datetime
from pathlib import Path


def setup_logging(
    root: Path,
    log_dir: str = "logs",
) -> None:
    log_dir_path = root / log_dir
    log_dir_path.mkdir(parents=True, exist_ok=True)

    file_handler = logging.FileHandler(
        log_dir_path / f"{datetime.now():%Y%m%dT%H%M%S}.log",
        encoding="utf-8",
    )
    file_handler.setFormatter(logging.Formatter(
        "%(asctime)s.%(msecs)03d | %(levelname)s | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    ))

    console_handler = logging.StreamHandler()
    console_handler.setFormatter(logging.Formatter(
        "%(asctime)s | %(levelname)s | %(message)s",
        datefmt="%Y-%m-%d %H:%M:%S",
    ))

    logging.basicConfig(
        level=logging.INFO,
        handlers=[file_handler, console_handler],
    )

main.py

呼び出し側で setup_logging() を一度実行し、logging.getLogger(__name__) でloggerを取得する。

import logging
from pathlib import Path

from logging_config import setup_logging


root = Path(__file__).resolve().parent

setup_logging(root)
logger = logging.getLogger(__name__)

logger.info("start")
logger.warning("something happened")
logger.error("failed")

デフォルトでは、以下のようなログファイルが作成される。

<root>/logs/20260906T073012.log

出力例

コンソールにはミリ秒なしで出力される。

2026-09-06 07:30:12 | INFO | start
2026-09-06 07:30:13 | WARNING | something happened
2026-09-06 07:30:14 | ERROR | failed

ログファイルにはミリ秒まで記録される。

2026-09-06 07:30:12.345 | INFO | start
2026-09-06 07:30:13.012 | WARNING | something happened
2026-09-06 07:30:14.891 | ERROR | failed

ファイル側では、

"%(asctime)s.%(msecs)03d | %(levelname)s | %(message)s"

としているため、ミリ秒まで記録される。

一方、コンソール側では %(msecs) を指定していないため、秒までの表示になる。

ログディレクトリを変更する

log_dir のデフォルトは "logs" なので、

setup_logging(root)

なら、

<root>/logs/

に出力される。

別のディレクトリに出力したければ、

setup_logging(root, log_dir="output/logs")

とする。

この場合は、

<root>/output/logs/

にログファイルが作成される。

mkdir(parents=True, exist_ok=True) としているため、途中のディレクトリも自動的に作成される。

複数モジュールから使う

setup_logging() はアプリケーションのエントリーポイントで一度だけ実行する。

例えば、

project/
├─ main.py
├─ logging_config.py
├─ loader.py
├─ analyzer.py
└─ logs/

の場合、main.py でloggingを設定する。

setup_logging(root)
logger = logging.getLogger(__name__)

loader.pyanalyzer.py では設定を繰り返さず、それぞれloggerを取得するだけでよい。

import logging


logger = logging.getLogger(__name__)


def load_data() -> None:
    logger.info("loading data")

logging.getLogger(__name__) とすることで、各モジュールの名前を持ったloggerを使用しつつ、エントリーポイントで設定したHandlerを共通して利用できる。

まとめ

Python標準の loggingloguru と比べると初期設定が長い。

ただし、設定部分を logging_config.pysetup_logging() にまとめてしまえば、エントリーポイント側は、

setup_logging(root)
logger = logging.getLogger(__name__)

logger.info("start")

程度で済む。

また、各モジュールでは、

logger = logging.getLogger(__name__)

だけで同じlogging設定を利用できる。

外部ライブラリを追加できない環境でも、標準ライブラリだけでコンソールとファイルへのログ出力を比較的シンプルに扱える。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?