In a python script I am writing, I am trying to log events using the logging module. I have the following code to configure my logger:
ERROR_FORMAT = "%(levelname)s at %(asctime)s in %(funcName)s in %(filename) at line %(lineno)d: %(message)s"DEBUG_FORMAT = "%(lineno)d in %(filename)s at %(asctime)s: %(message)s"LOG_CONFIG = {'version':1, 'formatters':{'error':{'format':ERROR_FORMAT}, 'debug':{'format':DEBUG_FORMAT}}, 'handlers':{'console':{'class':'logging.StreamHandler', 'formatter':'debug', 'level':logging.DEBUG}, 'file':{'class':'logging.FileHandler', 'filename':'/usr/local/logs/DatabaseUpdate.log', 'formatter':'error', 'level':logging.ERROR}}, 'root':{'handlers':('console', 'file')}}logging.config.dictConfig(LOG_CONFIG)When I try to runlogging.debug("Some string"), I get no output to the console, even thoughthis page in the docs says thatlogging.debug should have the root logger output the message. Why is my program not outputting anything, and how can I fix it?
11 Answers11
Many years later there seems to still be a usability problem with the Python logger. Here's some explanations with examples:
import logging# This sets the root logger to write to stdout (your console).# Your script/app needs to call this somewhere at least once.logging.basicConfig()# By default the root logger is set to WARNING and all loggers you define# inherit that value. Here we set the root logger to NOTSET. This logging# level is automatically inherited by all existing and new sub-loggers# that do not set a less verbose level.logging.root.setLevel(logging.NOTSET)# The following line sets the root logger level as well.# It's equivalent to both previous statements combined:logging.basicConfig(level=logging.NOTSET)# You can either share the `logger` object between all your files or the# name handle (here `my-app`) and call `logging.getLogger` with it.# The result is the same.handle = "my-app"logger1 = logging.getLogger(handle)logger2 = logging.getLogger(handle)# logger1 and logger2 point to the same object:# (logger1 is logger2) == Truelogger = logging.getLogger("my-app")# Convenient methods in order of verbosity from highest to lowestlogger.debug("this will get printed")logger.info("this will get printed")logger.warning("this will get printed")logger.error("this will get printed")logger.critical("this will get printed")# In large applications where you would like more control over the logging,# create sub-loggers from your main application logger.component_logger = logger.getChild("component-a")component_logger.info("this will get printed with the prefix `my-app.component-a`")# If you wish to control the logging levels, you can set the level anywhere # in the hierarchy:## - root# - my-app# - component-a## Example for development:logger.setLevel(logging.DEBUG)# If that prints too much, enable debug printing only for your component:component_logger.setLevel(logging.DEBUG)# For production you rather want:logger.setLevel(logging.WARNING)A common source of confusion comes from a badly initialised root logger. Consider this:
import logginglog = logging.getLogger("myapp")log.warning("woot")logging.basicConfig()log.warning("woot")Output:
wootWARNING:myapp:wootDepending on your runtime environment and logging levels,the first log line (before basic config) might not show up anywhere.
12 Comments
logging.basicConfig( filename='logging.txt', level=logging.DEBUG) logger = logging.getLogger() logger.info('Test B') logging.info('Test A')logger = logging.getLogger(), the level is set to WARNING even though I specified the level asDEBUG. Do you know what I'm doing wrong?import matplotlib.pyplot as plt after the logging import but before the rest of the code (which would follow pep8), the Matplotlib import borks the logging configuration and none of the logging messages are shown.The default logging level is warning.Since you haven't changed the level, the root logger's level is still warning.That means that it will ignore any logging with a level that is lower than warning, including debug loggings.
This is explained in thetutorial:
import logginglogging.warning('Watch out!') # will print a message to the consolelogging.info('I told you so') # will not print anythingThe 'info' line doesn't print anything, because the level is higher than info.
To change the level, just set it in the root logger:
'root':{'handlers':('console', 'file'), 'level':'DEBUG'}In other words, it's not enough to define a handler with level=DEBUG, the actual logging level must also be DEBUG in order to get it to output anything.
11 Comments
level != NOTSET or the root (if none is found). The root hasWARNING level by default. This is written in the section you've linked to (Logger.setLevel).logging you need to calllogging.basicConfig() at least once. Otherwise you might be badly surprised that child loggers will not print anything. Logging functions on the root logger call it lazily.'root':{'handlers':('console', 'file'), 'level':'DEBUG'} ?logging.basicConfig(level=logging.DEBUG). Thenlogging.debug(...) is supposed to be printed (They also show what is printed). Well, not in my case either! As for'root':{'handlers':('console', 'file'), 'level':'DEBUG'} ... How and where is this used??? You can't throw in a thing like this without an example of its application! I really wonder how such a bad and useless answer got so many upvotes! It should be downvoted instead! (I didn't, because I don't like that.)For anyone here that wants a super-simple answer: just set the level you want displayed. At the top of all my scripts I just put:
import logginglogging.basicConfig(level = logging.INFO)Then to display anything at or above that level:
logging.info("Hi you just set your fleeb to level plumbus")It is a hierarchical set of five levels so that logs will display at the level you set, orhigher. So if you want to display an error you could uselogging.error("The plumbus is broken").
The levels, in increasing order of severity, areDEBUG,INFO,WARNING,ERROR, andCRITICAL. The default setting isWARNING.
This is a good article containing this information expressed better than my answer:
https://www.digitalocean.com/community/tutorials/how-to-use-logging-in-python-3
3 Comments
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s: %(message)s')id __name__ == "__main__". But that does not work, basic configurations are not properly set. Where can be the problem?This problem wasted me so much time, so I'll just invest some more to write an answer and save yours
Problem
Cannot set logging level for custom loggers. (e.g: to DEBUG level)
What DOESN'T work
Setting logging level to the handler.
import logging# Get loggerlogger = logging.getLogger("my logger")# Create a handler and set logging level for the handlerc_handler = logging.StreamHandler()c_handler.setLevel(logging.DEBUG) # <- Here things went wrong# link handler to loggerlogger.addHandler(c_handler)# testlogger.debug('This is a debug message') # WILL NOT WORKSOLUTION
Set the logging level via the logger object (instead of the handler)Customlogger.setLevel(logging.DEBUG)
import logging# Get loggerlogger = logging.getLogger("my logger")# Create a handlerc_handler = logging.StreamHandler()# link handler to loggerlogger.addHandler(c_handler)# Set logging level to the loggerlogger.setLevel(logging.DEBUG) # <-- THIS!# testlogger.debug('This is a debug message') # WILL WORK3 Comments
Maybe try this? It seems the problem is solved after remove all the handlers in my case.
for handler in logging.root.handlers[:]: logging.root.removeHandler(handler)logging.basicConfig(filename='output.log', level=logging.INFO)5 Comments
SyntaxError: invalid syntaxlogging.root.handlers -- it will be an empty list). Callinglogging.basicConfig() adds aStreamHandler. So, the clearing of handlers is redundant.That simply works fine for me ...
import loggingLOGGER = logging.getLogger("my-fetcher")logging.basicConfig(level=logging.INFO)LOGGER.info("Established Connection Successfully!")# > INFO:my-fetcher:Established Connection Successfully!Comments
Nothing of the above worked for me when executing locally on my python environment, the following worked though,
import logginglogging.basicConfig()logger = logging.getLogger()logger.setLevel(logging.INFO)in my case I was missing thelogging.basicCofig()
1 Comment
baseConfig. :facepalm:import logginglog = logging.getLogger()log.setLevel(logging.DEBUG)
this code will set the default logging level to DEBUG.
4 Comments
logging within a Lambda -docs.aws.amazon.com/lambda/latest/dg/…The key point is that you must set the logging level on a logging handler object,as well as the logger object itself:
Here's an example setup. (You place this somewhere at the top of your executable Python script, outside ofdef main() /if __name__ == '__main__'.)
logger = logging.getLogger(__name__)stdout_log_formatter = logging.Formatter( '%(name)s: %(asctime)s | %(levelname)s | %(filename)s:%(lineno)s | %(process)d | %(message)s')stdout_log_handler = logging.StreamHandler(stream=sys.stdout)stdout_log_handler.setLevel(logging.INFO)stdout_log_handler.setFormatter(stdout_log_formatter)logger.addHandler(stdout_log_handler)logger.setLevel(logging.INFO)I have included a couple of extras like a format specification for your convenience.
Comments
Calling removeHandler() function leaves stdout/stderr output even though all handlers have been removed.
one way to cleanup a logger is to empty the list of handlers, i.e.logger.handlers = []orlogger.root.handlers = []
This worked for me.
Comments
I was also using the root logger and not seeing any logs, i.e.
import logging.. other codelogging.debug("Hello World")I tried setting the basicConfig but I found the only way it would work, was to useforce = True.
import logginglogging.basicConfig( level=logging.DEBUG, force=True).. other codelogging.debug("Hello World")https://docs.python.org/3/library/logging.html#logging.basicConfig
force. If this keyword argument is specified as true, any existing handlers attached to the root logger are removed and closed, before carrying out the configuration as specified by the other arguments.
Comments
Explore related questions
See similar questions with these tags.
















