0

Consider the following piece of code:

import logging

logging.info("toto")

logging.basicConfig(level="INFO",
                    format="%(asctime)s - %(threadName)s -"
                    " %(levelname)s"
                    " - [%(funcName)s():%(filename)s:%(lineno)s]"
                    " - %(message)s")
logging.info("info")
logging.error("error")
logging.warning("warn")
logging.debug("debug")

The output is the following:

$ python mmt_test.py 
ERROR:root:error
WARNING:root:warn

However, with the following code:

import logging

logging.basicConfig(level="INFO",
                    format="%(asctime)s - %(threadName)s -"
                    " %(levelname)s"
                    " - [%(funcName)s():%(filename)s:%(lineno)s]"
                    " - %(message)s")
logging.info("info")
logging.error("error")
logging.warning("warn")
logging.debug("debug")

The output is:

$ python mmt_test.py 
2021-12-07 07:44:46,711 - MainThread - INFO - [<module>():mmt_test.py:8] - info
2021-12-07 07:44:46,711 - MainThread - ERROR - [<module>():mmt_test.py:9] - error  
2021-12-07 07:44:46,711 - MainThread - WARNING - [<module>():mmt_test.py:10] - warn

In the first code sample, why isn't basicConfig applied to the logs ? Does using the logging module before using basicConfig prevents to use basicConfig afterwards ?

This happens in python 3.5.2, 3.8.3 and 3.9

Kota Mori
  • 6,510
  • 1
  • 21
  • 25
Itération 122442
  • 2,644
  • 2
  • 27
  • 73

1 Answers1

1

The call to basicConfig() should come before any calls to debug(), info() etc. As it’s intended as a one-off simple configuration facility, only the first call will actually do anything: subsequent calls are effectively no-ops.

Source: https://docs.python.org/3/howto/logging.html#logging-to-a-file

This says that the basicConfig() call is only one-off. Only the first one will be effective.

The functions debug(), info(), warning(), error() and critical() will call basicConfig() automatically if no handlers are defined for the root logger.

Source: https://docs.python.org/3/library/logging.html#logging.basicConfig

This says that the functions like debug(), info(), etc, will call the basicConfig() automatically if no handler is set.

So based on the above two statements, it is clear that in your first example, when you called logging.info("toto"), it automatically calls the logging.basicConfig() as no handler is set.

Therefore, on your call of logging.basicConfig(), it does nothing, as specified in the docs.

One more relevant quote from the python3 logging docs

By default, no destination is set for any logging messages. You can specify a destination (such as console or file) by using basicConfig() as in the tutorial examples. If you call the functions debug(), info(), warning(), error() and critical(), they will check to see if no destination is set; and if one is not set, they will set a destination of the console (sys.stderr) and a default format for the displayed message before delegating to the root logger to do the actual message output.

Source: https://docs.python.org/3/howto/logging.html#advanced-logging-tutorial

In conclusion, if you call logging.info() or the logging related functions, before setting the formatter and handler using logging.basicConfig(), they will just default to the default handler and format. If you want the message to have specific formatting and handler, you have to call logging.basicConfig() before logging anything.

thuyein
  • 1,684
  • 13
  • 29