I'm working on a small python project that has the following structure -
project
-- logs
-- project
__init.py__
classA.py
classB.py
utils.py
-- main.py
I've set up the logging configuration in __init.py__
under project as follows:
import logging
from logging import StreamHandler
from logging.handlers import RotatingFileHandler
# Create the Logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
# Create the Handler for logging data to a file
logger_handler = RotatingFileHandler('logs\\mylog.log', maxBytes=1024, backupCount=5)
logger_handler.setLevel(logging.INFO)
#Create the Handler for logging data to console.
console_handler = StreamHandler()
console_handler.setLevel(logging.INFO)
# Create a Formatter for formatting the log messages
logger_formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
# Add the Formatter to the Handler
logger_handler.setFormatter(logger_formatter)
console_handler.setFormatter(logger_formatter)
# Add the Handler to the Logger
logger.addHandler(logger_handler)
logger.addHandler(console_handler)
Setting up things this way seems to set up the root logger at the package level, and not at the entire project level. As a result, logged statements inside main.py
don't appear in the log file, whereas all log statements in the two classes classA
and classB
as well as utils.py
are routed to the console and the log file as expected.
How do I set up the logging so that I'm able to configure it once and use it across the project? I tried moving the logging configuration statements to main.py, but it didn't seem to work.
def setupLogging():
# Create the Logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
..etc..
def main():
setupLogging()
if __name__ == "__main__":
main()
You can set a different logging level for each logging handler but it seems you will have to set the logger's level to the "lowest". In the example below I set the logger to DEBUG, the stream handler to INFO and the TimedRotatingFileHandler to DEBUG. So the file has DEBUG entries and the stream outputs only INFO.
The logging module is thread-safe; it handles the locking for you.
logger = logging. getLogger(__name__) This means that logger names track the package/module hierarchy, and it's intuitively obvious where events are logged just from the logger name. The root of the hierarchy of loggers is called the root logger.
It is correct to configure logging only once for the whole project, as you first tried, not each package separately.
What you did wrong is you configured the logger for the current module only:
logger = logging.getLogger(__name__)
Instead of that, you want to configure the root logger:
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)
# ...
root_logger.addHandler(logger_handler)
root_logger.addHandler(console_handler)
The configuration done for the root logger applies to every logger which does not explicitly override it.
Then you should use the specific logger when actually logging:
logger = logging.getLogger(__name__)
logger.warning("I am warning you about %s", something)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With