python / python/cpython

MemoryHandler can't be setup through a DictConfig if any other logger is setup after it

オープン
#123,239 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

stdlib type-bug
主要言語
Python
スター
77.2k
フォーク
35.9k
PR マージ指標
PR 指標を取得中

説明

Bug report

Bug description:

This is the logging that's failing.

LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "fine-logger1": {
            'level': logging.INFO,
            'formatter': 'verbose-console',
            'class': 'logging.StreamHandler',
            'stream': 'ext://sys.stdout',
        },
        "fine-logger2": {
            "level": logging.INFO,
            "class": "logging.FileHandler",
            "filename": Path("logs/somefilename.log"),
            "mode": "a",
            "formatter": "verbose",
        },
        "fine-logger3": {
            "level": logging.DEBUG,
            "class": "logging.FileHandler",
            "filename": Path("logs/errors/somefilename.log"),
            "delay": True,
            "formatter": "verbose",
        },
        "bugged-logger3": {
            "level": logging.DEBUG,
            "class": "logging.handlers.MemoryHandler",
            "capacity": 9999999,
            "flushLevel": logging.ERROR,
            "target": "fine-logger3",
            "flushOnClose": False,
        },
    },
    "loggers": {
        "bug-logger": {
            "handlers": ["fine-logger1", "fine-logger2", "bugged-logger3"],
            "level": logging.DEBUG,
            "propagate": True
        },
    },
}

After it's been setup, if any other handler is setup afterwards (in my case it's the copernicusmarine logger) the handler bugged-logger3 will have a None inside its target field, as every handler that's not incremental will delete existing unused handlers.

I've dug into the source code of logging and I think I've tracked down where this is happpening, but I'm not really sure on how to fix it.
In the config file python3.11/logging/config.py in the configure() function there's a call to _clearExistingHandlers():

            else:
                disable_existing = config.pop('disable_existing_loggers', True)

                _clearExistingHandlers() <-----

                # Do formatters first - they don't refer to anything else
                formatters = config.get('formatters', EMPTY_DICT)
                for name in formatters:
                    try:
                        formatters[name] = self.configure_formatter(
                                                            formatters[name])

If we comment this line, it works completely fine. But I guess this just keeps handlers loaded in memory and that's not a proper solution.

CPython versions tested on:

3.11

Operating systems tested on:

Linux

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

python3.11/logging/config.py、特に DictConfig.configure() と _clearExistingHandlers() から始めます。提供された設定を再現し、その後別の logger を設定して、MemoryHandler.target が None になるかを確認します。後続の非インクリメンタル設定によって MemoryHandler の target が壊れなくなり、handler のクリーンアップも引き続き正しく動作すれば完了です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
tooling
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
35/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。