Python logging messages get printed twice when importing package that use logging themselves

Viewed 162

When importing an external package such as open3d that uses Pythons logging functionality, my own logging gets printed twice.

See this example:

import logging
import open3d as o3d

logger = logging.getLogger(__name__)


def main():
    # set base level of logger on a module level
    logger.setLevel(logging.DEBUG) 
    # create file handler which logs even debug messages
    fh = logging.FileHandler('log.log')
    fh.setLevel(logging.DEBUG)
    # create console handler with a higher log level
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    # create formatter and add it to the handlers
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    ch.setFormatter(formatter)
    # add the handlers to the logger
    logger.addHandler(fh)
    logger.addHandler(ch)


    logger.info('This gets printed twice to console and once to log file.')


if __name__=="__main__":
    main()

Console output:

2022-03-29 15:06:20,533 - __main__ - INFO - This gets printed twice to console and once to log file.
INFO - 2022-03-29 15:06:20,533 - test - This gets printed twice to console and once to log file.

What would be the standard way to handle such a case where a logger exists in a external package? Is there a possibility to catch the logger from open3d and incorporate its messages into my own logger? Can I mute it altogether? Thanks for the help!

Solution that worked for me:
With the hint from @Cargo23's answer and the help of this question, I was able to inspect all the loggers and handlers and found a StreamHandler in the RootLogger. With these lines just after the imports I was able to remove it:

rootlogger = logging.getLogger() 
rootlogger.handlers.pop() 

Although, I am not fully satisfied with this solution, as it does not seem very generic.

1 Answers

The short answer is, yes you can. Its always been a hassle when I've done this, but here are some guide posts:

The logging library has lists of the active loggers, formatters, and handlers that you can access.

Ultimately, you want to remove the handler that your library is adding. I think that the handler can be attached to their logger and/or the root logger.

I think you can even just remove all the handlers and then add your own back in.

Hope it helps!

Related