logging.info doesn't show up on console but warn and error do
Asked Answered
G

10

153

When I log an event with logging.info, it doesn't appear in the Python terminal.

import logging
logging.info('I am info')  # no output

In contrast, events logged with logging.warn do appear in the terminal.

import logging
logging.warn('I am warning')  # outputs "I am warning"

Is there a environment level change I can to make logging.info print to the console? I want to avoid making changes in each Python file.

Gotthard answered 18/7, 2012 at 19:14 Comment(0)
B
222

The root logger always defaults to WARNING level. Try calling

logging.getLogger().setLevel(logging.INFO)

and you should be fine.

Birthday answered 18/7, 2012 at 19:19 Comment(13)
this works well, but I think I will have to change it in every python file I have right? there is no global setting for LOGGINGGotthard
No, you only need to call it once. The logger is built as a hierarchy with and all logging boils down to a root logger. By not specifying any argument to getLogger(), it is returning you the root logger. As long as you don't modify the other loggers you only need to modify the root logger.Birthday
Do you know why logging.basicConfig(level=logging.INFO) doesn't work? I can't see it clearly on the documentation.Labium
Isn't logging.basicConfig(level=logging.INFO) the preferred way to do that?Sheley
@P1h3r1e3d13 If you only have a single root logger that's likely best-practises, yes.Birthday
This Does not work on Python 3.5: Python 3.5.2 (default, Nov 12 2018, 13:43:14) [GCC 5.4.0 20160609] on linux >>> import logging >>> rootLog = logging.getLogger() >>> rootLog.setLevel(logging.INFO) >>> rootLog.info('all the kings horses') >>> rootLog.warning('all the kings men') all the kings menMasterpiece
FWIW, this post explains why the root logger and logging module level method calls are best avoided: electricmonk.nl/log/2017/08/06/… The tl;dr is: "Don’t log directly against the root logger. That means: no logging.basicConfig() and no usage of module-level loggers such as logging.warning(), as they have unintended side-effects."Knobkerrie
@jeffk, same with me 3.6.8 doesn't print info messages even when setLevel is set to logging.INFOCharnel
@RobertLugg Same here in 3.7, set my logger to logging.INFO and nothing is showing up unless I use logger.warning()Julissajulita
Use "root" to actually set the root. I.E. "logging.root.setLevel(logging.NOTSET)"Zonnya
Will this method have unintended consequences? I'm just afraid that reconfiguring root logger after having child loggers is not the best idea. I'm not well-versed in python's logging,Houseless
This will not work for Python 3.2 and later, since root logger without explict handlers will use the logging.lastResort handler and its level is WARNING. See also the official doc: docs.python.org/3/howto/….Osithe
Sometimes defining a stream helps: logging.basicConfig(level=logging.DEBUG, stream=sys.stdout)Bountiful
D
52

Like @ztyx said that default logger level is WARNING. You have to set it to a lower level

You can do it by using logging.basicConfig and setting logger level:

logging.basicConfig(level=logging.DEBUG)
Desperado answered 11/10, 2018 at 13:43 Comment(2)
I'm wondering why basicConfig() doesn't work for me, although logging.getLogger().setLevel() suitably work?Dubose
@ShayanAmani - According to the documentation, "This function does nothing if the root logger already has handlers configured, unless the keyword argument force is set to True."Witted
H
31

The above solutions didn't work for me, but the code here did:

# set up logging to file
logging.basicConfig(level=logging.DEBUG,
                    format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
                    datefmt='%m-%d %H:%M',
                    filename='/temp/myapp.log',
                    filemode='w')
# define a Handler which writes INFO messages or higher to the sys.stderr
console = logging.StreamHandler()
console.setLevel(logging.INFO)
# add the handler to the root logger
logging.getLogger('').addHandler(console)

(I omitted parts of the code for the sake of readability)

Haeres answered 27/11, 2018 at 9:17 Comment(3)
This is the only thing that worked for me. I had a line with logging.error("Connection timed out!") and even with the level=logging.DEBUG in the basicConfig(), it wouldn't print to console. Adding the handler did, thanks so much!!Yuriyuria
Keep in mind that the handler you are using is playing a role. If, for example, your code had the NullHandler, nothing would be printed regardless of the logging lever.Prankster
Same here - if i omit the level argument in basicConfig or set it above INFO then the console logger will never log anything. If i leave out basicConfig then i can call setLevel on a logger all day (and i can see the level change by calling getEffectiveLevel) but it will never log anything below WARNING level. I'm not actually sure that that isnt the correct behaviour but its not what I was expecting.Forcier
B
18

This will work

import logging

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

logger.info('its working')
Brotherton answered 18/6, 2021 at 5:51 Comment(0)
T
7

In more recent versions of Python 3 (tested with Python 3.8), console logging requires creating a console handler to correctly show info messages.

The following example is modified from the Configuring Logging example in the Python documentation:

import logging

# create logger
logger = logging.getLogger('__name__')
level = logging.INFO
logger.setLevel(level)

# ----> console info messages require these lines <----
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(level)

# add ch to logger
logger.addHandler(ch)
# -----------------------------------------------------

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

Running the above code generates the following output:

info message
warn message
error message
critical message

Here is this same code without the console handler.

import logging

# create logger
logger = logging.getLogger('__name__')
level = logging.INFO
logger.setLevel(level)

# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')

Without the console handler, the output does not include the info message:

warn message
error message
critical message

I do not understand why this is the case as it seems unnecessary.

Thyrse answered 8/8, 2022 at 21:44 Comment(1)
weird, I can confirm streamhandler is necessary. Thanks for saving my timeRegistrant
C
4

What's the minimum required code for a working module-level logger? I did an experiment (with python version 3.8.6).

The take-away is:

  • logging.basicConfig() is needed (however, specifying level=... is NOT needed)
  • it's necessary to configure the root logger: logging.getLogger().setLevel(...)

So, a minimum working example is:

The library/module code does NOT need to configure the logger:

# library/module code: lib.py
import logging
LOGGER = logging.getLogger('x.y.z')

def some_function():
    LOGGER.info("hi")

The application code need to configure the logger with 2 lines at minimum:

# Application Code
import logging, lib

logging.basicConfig()
logging.getLogger().setLevel(logging.INFO)  # configure root logger

main()  # code that will trigger lib

Here's the experiment:

In [1]: import logging

In [2]: lg = logging.getLogger('x.y.z')

In [3]: lg.info(1)

In [4]: logging.basicConfig()

In [5]: lg.info(1)

In [6]: logging.basicConfig(level=logging.INFO)

In [7]: lg.info(1)

In [8]: logging.basicConfig()

In [9]: logging.getLogger().setLevel(logging.INFO)

In [10]: lg.info(1)
INFO:x.y.z:1
Crag answered 12/12, 2021 at 7:1 Comment(1)
Why isn't logging.basicConfig(level=logging.INFO) enough? Is this a bug?Orography
I
1

If you are using Django to power your server, you just simply need to change the log level in your settings.py file as such:

"handlers": {
                "console": {
--                  "level": "WARNING",
++                  "level": "INFO",
                    "class": "logging.StreamHandler",
                    "formatter": "stackdriver",
                }
            },

More examples in the documentation here: https://docs.djangoproject.com/en/4.0/topics/logging/#configuring-logging-1

Indirection answered 12/4, 2022 at 12:17 Comment(0)
A
0

For those using absl.logging, the equivalent command is

from absl import logging
logging.set_verbosity(logging.INFO)
Annieannihilate answered 12/10, 2021 at 21:58 Comment(0)
O
0

logging.info() will use the root logger for logging.

According to official doc, if you do not set an explicit handler for the logger, a special handler called lastResort will be used. See the code here. By default the logging level of lastResort (it is stream handler) is 30. we can change its level to output info message.

# setting both the logger and handler's level will work as expected.
logger.setLevel(logging.DEBUG)
logging.lastResort.setLevel(logging.DEBUG)

However, this is like a hack and never a encouraged action.

Using logging.basicConfig()

If we want to do logging real quick, we can use the method logging.basicConfig.

logging.basicConfig(level=logging.DEBUG)

This will create the logger. The logger.level will be the level we set here. A stream handler will be also created, with level NOTSET. Without a level param, the default level for root logger is WARNING.

reference

Osithe answered 27/5, 2022 at 9:52 Comment(0)
T
0

I usually use config like this:

logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S", filename=f"./logs/app_log_{datetime}.log")
Tybie answered 13/2 at 23:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.