Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 683
GregT Avatar asked Jan 29 '19 14:01

GregT


2 Answers

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)
like image 156
Marcus Avatar answered Oct 08 '22 09:10

Marcus


Looking through a similar issue on the Python bug tracker (https://bugs.python.org/issue16368), you can see that the formatter argument is expected to be a string (hence the attempt to invoke find):

log_format = '[%(asctime)s] [%(levelname)s] - %(message)s'
logging.basicConfig(level=self.log_level, format=log_format)
like image 26
Mad Physicist Avatar answered Oct 08 '22 10:10

Mad Physicist