Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python logging why outputing twice?

Tags:

python

I have the following code setting up the logger:

import logging

logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO)
log = logging.getLogger()
handler = logging.StreamHandler(sys.stdout)
log.addHandler(handler)

log.info('abc')

When I run it, I get output like:

2020-06-10 13:32:16,245 INFO: abc
abc

I presume the first one is the console output? How do I get rid of the duplicate one?

UPDATE

Thanks guys for the answers, now I know why I get duplicates, the reason I did it this way because the default stream handler does not output to stdout, so I googled and saw someone adding a stdout handler, hence I got 2 stream handlers (console and stdout).

I have now read again the documentation about the basicConfig() and I have worked out the easiest way to achieve what I want:

import sys
import logging

log = logging.getLogger(__name__)
logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO, stream=sys.stdout)

log.info('abc')
like image 827
James Lin Avatar asked Jun 10 '20 01:06

James Lin


People also ask

How does logging level work Python?

Logging Levels When you set a logging level in Python using the standard module, you're telling the library you want to handle all events from that level on up. If you set the log level to INFO, it will include INFO, WARNING, ERROR, and CRITICAL messages. NOTSET and DEBUG messages will not be included here.

What is the purpose of logging Python?

Logging is a means of tracking events that happen when some software runs. Logging is important for software developing, debugging, and running. If you don't have any logging record and your program crashes, there are very few chances that you detect the cause of the problem.


Video Answer


1 Answers

This call to logging.basicConfig will already add a stream handler (to stderr), so there is no reason to add another stream handler manually. Doing so will cause duplicate output to the terminal, in your case each log event is printing on both stderr and stdout.

If you want the stream handler to stdout instead of stderr, just adjust the basicConfig call accordingly by specifying the stream or the handlers keywords (docs).

There are two other things you could clean up: use a logger bound to the module __name__ context rather than using the root logger directly, and avoid to configure the logging module at import time. If you configure the logging system too eagerly at import time, then the user (and the test suite) is no longer able to configure it differently.

import logging

# create your logger as module level global
log = logging.getLogger(__name__)

def main():
    # configure logging at entry point (so it is not configured at *import* time)
    fmt = '%(asctime)s %(levelname)s: %(message)s'
    logging.basicConfig(format=fmt, level=logging.INFO)  # streamhandler to stderr
    log.info('abc')


if __name__ == "__main__":
    main()
like image 183
wim Avatar answered Oct 22 '22 23:10

wim