pythonpython-3.xloggingattributeerrorformatter

Python logging to console


I'm trying to create a log in Python 3.x, that writes out to the console. Here is my code:

import logging
import sys

class Temp:
    def __init__(self, is_verbose=False):
        # configuring log
        if (is_verbose):
            self.log_level=logging.DEBUG
        else:
            self.log_level=logging.INFO

        log_format = logging.Formatter('[%(asctime)s] [%(levelname)s] - %(message)s')
        logging.basicConfig(level=self.log_level, format=log_format)
        self.log = logging.getLogger(__name__)

        # writing to stdout
        handler = logging.StreamHandler(sys.stdout)
        handler.setLevel(self.log_level)
        handler.setFormatter(log_format)
        self.log.addHandler(handler)

        # here
        self.log.debug("test")

if __name__ == "__main__":
    t = Temp(True)

If the line after "here" is entered, Python raises an error:

[2019-01-29 15:54:20,093] [DEBUG] - test
--- Logging error ---
Traceback (most recent call last):
  File "C:\Programok\Python 36\lib\logging\__init__.py", line 993, in emit
    msg = self.format(record)
  File "C:\Programok\Python 36\lib\logging\__init__.py", line 839, in format
    return fmt.format(record)
  File "C:\Programok\Python 36\lib\logging\__init__.py", line 577, in format
    if self.usesTime():
  File "C:\Programok\Python 36\lib\logging\__init__.py", line 545, in usesTime
    return self._style.usesTime()
  File "C:\Programok\Python 36\lib\logging\__init__.py", line 388, in usesTime
    return self._fmt.find(self.asctime_search) >= 0
AttributeError: 'Formatter' object has no attribute 'find'
...

I also had some other places in my code that prints to the log, but nothing is written to stdout, even if the line after "here" is removed.

What might be the problem?


Solution

  • The problem comes from the call to basicConfig which sets up a log handler for stderr and also accepts a format string, not a formatter. Because you are doing this work yourself later, you don't need to use the basicConfig function. More information can be found in the python documentation.

    Removing the call to basicConfig, and adding a self.log.setLevel(self.log_level) will fix the issue you are seeing.

    Working code:

    import logging                                                                  
    import sys                                                                      
    
    class Temp:                                                                     
        def __init__(self, is_verbose=False):                                       
            # configuring log                                                       
            if (is_verbose):                                                        
                self.log_level=logging.DEBUG                                        
            else:                                                                   
                self.log_level=logging.INFO                                         
    
            log_format = logging.Formatter('[%(asctime)s] [%(levelname)s] - %(message)s')
            self.log = logging.getLogger(__name__)                                  
            self.log.setLevel(self.log_level)                                       
    
            # writing to stdout                                                     
            handler = logging.StreamHandler(sys.stdout)                             
            handler.setLevel(self.log_level)                                        
            handler.setFormatter(log_format)                                        
            self.log.addHandler(handler)                                            
    
            # here                                                                  
            self.log.debug("test")                                                  
    
    if __name__ == "__main__":                                                      
        t = Temp(True)