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')
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.
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.
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()
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