pythonloggingpython-logging

logger from Jupyter notebook: does not work unless calling the root logger at least once


I would like to see the logging produced by some Python code from within a Jupyter notebook (logging version '0.5.1.2', python 3.12).

If I run the following code:

import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

logger.info("logging test")

I get no output.

But if I call the root logging first in a notebook cell:

import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

logging.info("logging test")  # calling the root logger

I get the expected "logging test", and every other subsequent logged message, like:

logger.info("another logging test")

works correctly.

So within the same session, if I do not call the root logger at least once, no logging message is shown. But if I run the root logger at least once, all works correctly.

Any idea or explanation why is it the case, or if I am doing something wrong?


Solution

  • Explanation

    From the docs:

    This is a convenience function that calls Logger.debug(), on the root logger. The handling of the arguments is in every way identical to what is described in that method.

    The only difference is that if the root logger has no handlers, then basicConfig() is called, prior to calling debug on the root logger.

    The behaviour for logging.info is the same.

    When you call logging.getLogger(), you actually get the root logger, so in both examples, the root logger is used. However, you didn't add a handler to that root logger, which is only done automatically when you call one of the module level convenience functions (like logging.info)

    What to do instead

    It is recommended to create a new logger rather than using the root logger, by passing a name to logging.getLogger(). Typically, the modules name is used:

    logger = logging.getLogger(__name__)
    

    Before you can use it, you have to add a handler to it with .addHandler():

    handler = logging.StreamHandler()
    logger.addHandler(handler)
    

    Note that a logger object can have multiple handlers and that each handler has its own log_level. To modify the exact output of a handler, you can create a formatter and use it with handler.setFormatter()

    Relevant links