Python logging module having a formatter causes AttributeError

21,871

Instead of

handler = logging.StreamHandler(stdout).setFormatter(formatter)

Try:

handler = logging.StreamHandler(stdout)
handler.setFormatter(formatter)

What is happening is that in the first case you are assigning the return of setFormatter() to the handler variable, but setFormatter() does not return the handler (i.e. it returns None)

Share:
21,871
sjaustirni
Author by

sjaustirni

Updated on December 17, 2020

Comments

  • sjaustirni
    sjaustirni over 3 years

    I am writing a terminal application, which, after passing in -v option, gets, unsurprisingly, verbose. I want to have the output available in the terminal, for easy testing (it gets redirected to a log file when running as cron anyways).

    However, python logging module doesn't allow me to write out the messages with corresponding levels when using a formatter. (Formatter is copied directly from Python Logging Cookbok)

    This behavior is not limited to Python3 only. Python2.7 raises the same exception under the given conditions.


    one.py

    from sys import stdout
    import logging
    
    if __name__ == '__main__':
    
        level = 20
    
        log = logging.getLogger()
        formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
        handler = logging.StreamHandler(stdout).setFormatter(formatter)
        log.addHandler(handler)
        log.setLevel(level)
    
        log.info("Blah")
    

    one.py output

    Traceback (most recent call last):
      File "/home/tlevi/PycharmProjects/untitled/main.py", line 14, in <module>
        log.info("Blah")
      File "/usr/lib/python3.4/logging/__init__.py", line 1279, in info
        self._log(INFO, msg, args, **kwargs)
      File "/usr/lib/python3.4/logging/__init__.py", line 1414, in _log
        self.handle(record)
      File "/usr/lib/python3.4/logging/__init__.py", line 1424, in handle
        self.callHandlers(record)
      File "/usr/lib/python3.4/logging/__init__.py", line 1485, in callHandlers
        if record.levelno >= hdlr.level:
    AttributeError: 'NoneType' object has no attribute 'level'
    

    two.py (works like a charm)

    from sys import stdout
    import logging
    
    if __name__ == '__main__':
    
        level = 20
    
        log = logging.getLogger()
        handler = logging.StreamHandler(stdout)
        log.addHandler(handler)
        log.setLevel(level)
    
        log.info("Blah")
    

    two.py output

    Blah
    
  • Rikaelus
    Rikaelus about 6 years
    The lack of support for chaining in such a popular library is disappointing.
  • barrypicker
    barrypicker about 5 years
    @Rikaelus - it begs the question "why is it popular?"