This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: parent logger should also check the level
Type: behavior Stage: resolved
Components: Library (Lib) Versions:
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: qingyunha, r.david.murray, vinay.sajip
Priority: normal Keywords:

Created on 2017-07-06 01:06 by qingyunha, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 2604 merged vinay.sajip, 2017-07-06 16:45
Messages (10)
msg297791 - (view) Author: TaoQingyun (qingyunha) * Date: 2017-07-06 01:11
```
import logging

logging.basicConfig(level=logging.ERROR)

l = logging.getLogger("test")
l.setLevel(logging.DEBUG)

l.debug("Hello world")
```
it will print 'Hello world'
msg297799 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-07-06 04:19
I will let Vinay answer definitively, but this is working as designed.  This allows you to set 'debug' level on a sub-logger without getting debug output for every logger in your system, which is what you would get otherwise as the default logging level is NOTSET.

The documentation for setLevel could probably be improved slightly in this regard, as currently you have to infer this behavior from the fact that NOTSET causes the ancestor logger's level to be used, implying that if you set it, that setting is used and not the ancestor logger's level.
msg297810 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2017-07-06 07:10
As RDM says, this behaviour is as designed. The logger's setLevel documentation says:

"Sets the threshold for this logger to lvl. Logging messages which are less severe than lvl will be ignored. When a logger is created, the level is set to NOTSET (which causes all messages to be processed when the logger is the root logger, or delegation to the parent when the logger is a non-root logger). Note that the root logger is created with level WARNING.

The term ‘delegation to the parent’ means that if a logger has a level of NOTSET, its chain of ancestor loggers is traversed until either an ancestor with a level other than NOTSET is found, or the root is reached.

If an ancestor is found with a level other than NOTSET, then that ancestor’s level is treated as the effective level of the logger where the ancestor search began, and is used to determine how a logging event is handled.

If the root is reached, and it has a level of NOTSET, then all messages will be processed. Otherwise, the root’s level will be used as the effective level."

Not sure how I can improve upon that, as it seems clear enough, but any suggestions are welcome.
msg297814 - (view) Author: TaoQingyun (qingyunha) * Date: 2017-07-06 08:17
yes, I understand the effective level. my question is that before call ancestor's handler, should also check `c.isEnabledFor(record.levelno)`

```
    def callHandlers(self, record):
        """
        Pass a record to all relevant handlers.

        Loop through all handlers for this logger and its parents in the
        logger hierarchy. If no handler was found, output a one-off error
        message to sys.stderr. Stop searching up the hierarchy whenever a
        logger with the "propagate" attribute set to zero is found - that
        will be the last logger whose handlers are called.
        """
        c = self 
        found = 0
        while c:
            for hdlr in c.handlers:
                found = found + 1
                if record.levelno >= hdlr.level:
                    hdlr.handle(record)
            if not c.propagate:
                c = None    #break out
            else:
                c = c.parent
...
```
msg297830 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2017-07-06 13:58
@qingyunha: we are telling you that that would *introduce* a bug.  This is working the way it is supposed to.

Vinay, what if we rewrote the beginning of that paragraph like this:

Sets the threshold for this logger to lvl. Logging messages which are less severe than lvl will be ignored, logging messages which have severity lvl or higher will be emitted by whichever handler or handlers service this logger, unless the handler's level has been set to a higher severity level than lvl.

When a logger is created, the level is set to NOTSET....
msg297834 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2017-07-06 16:51
New changeset 0653fba51c03d20fa4381ba0836acd17fd05b04b by Vinay Sajip in branch 'master':
bpo-30862: Updated Logger.setLevel documentation. (GH-2604)
https://github.com/python/cpython/commit/0653fba51c03d20fa4381ba0836acd17fd05b04b
msg307535 - (view) Author: TaoQingyun (qingyunha) * Date: 2017-12-04 03:11
Maybe I misunderstand. At least the basicConfig should also set the level of the handler that it created.
msg307765 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2017-12-06 19:30
> Maybe I misunderstand.

I think you do misunderstand. The level of the handler created by basicConfig doesn't have any level set, so it will process any message it is asked to handle. This is working as designed.
msg307787 - (view) Author: TaoQingyun (qingyunha) * Date: 2017-12-07 03:54
Sorry to disturb. When calling `logging.basicConfig(level=logging.ERROR)`, I expect only the ERROR or above level will be logged. so the level argument if set should also pass to the handler.
msg307818 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2017-12-07 16:41
basicConfig() provides default behaviour for simple cases. If you don't like the defaults it provides, you can choose your own configuration code to do exactly what you want.
History
Date User Action Args
2022-04-11 14:58:48adminsetgithub: 75045
2017-12-07 16:41:19vinay.sajipsetmessages: + msg307818
2017-12-07 03:54:04qingyunhasetmessages: + msg307787
2017-12-06 19:30:01vinay.sajipsetmessages: + msg307765
2017-12-04 03:11:49qingyunhasetmessages: + msg307535
2017-07-06 16:51:30vinay.sajipsetmessages: + msg297834
2017-07-06 16:45:53vinay.sajipsetpull_requests: + pull_request2672
2017-07-06 13:58:43r.david.murraysetmessages: + msg297830
2017-07-06 08:17:15qingyunhasetmessages: + msg297814
2017-07-06 07:10:11vinay.sajipsetstatus: open -> closed
resolution: not a bug
messages: + msg297810

stage: resolved
2017-07-06 04:19:59r.david.murraysetnosy: + r.david.murray
messages: + msg297799
2017-07-06 04:00:32ned.deilysetnosy: + vinay.sajip
2017-07-06 01:11:03qingyunhasetmessages: + msg297791
2017-07-06 01:06:28qingyunhacreate