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
The formatter returns formatted output to the handler, which writes the output to the output device. The formatter is responsible for rendering the event for output. This formatter uses the resource bundle that is specified in the event to look up the message in the appropriate language.
Although logging module is thread-safe, it's not process-safe. If you want multiple processes to write to the same log file, then you have to manually take care of the access to your file.
The qualname entry is the hierarchical channel name of the logger, that is to say the name used by the application to get the logger.
Configuring Logging Creating loggers, handlers, and formatters explicitly using Python code that calls the configuration methods listed above. Creating a logging config file and reading it using the fileConfig() function. Creating a dictionary of configuration information and passing it to the dictConfig() function.
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
)
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