I asked this question for python 2 here, but bumped into the issue again when the the answer no longer worked for Python 3.2.3.
Here's code that works on Python 2.7.3:
import logging # Attempt to set up a Python3 logger than will print custom messages # based on each message's logging level. # The technique recommended for Python2 does not appear to work for # Python3 class CustomConsoleFormatter(logging.Formatter): """ Modify the way DEBUG messages are displayed. """ def __init__(self, fmt="%(levelno)d: %(msg)s"): logging.Formatter.__init__(self, fmt=fmt) def format(self, record): # Remember the original format format_orig = self._fmt if record.levelno == logging.DEBUG: self._fmt = "DEBUG: %(msg)s" # Call the original formatter to do the grunt work result = logging.Formatter.format(self, record) # Restore the original format self._fmt = format_orig return result # Set up a logger my_logger = logging.getLogger("my_custom_logger") my_logger.setLevel(logging.DEBUG) my_formatter = CustomConsoleFormatter() console_handler = logging.StreamHandler() console_handler.setFormatter(my_formatter) my_logger.addHandler(console_handler) my_logger.debug("This is a DEBUG-level message") my_logger.info("This is an INFO-level message")
A run using Python 2.7.3:
tcsh-16: python demo_python_2.7.3.py DEBUG: This is a DEBUG-level message 20: This is an INFO-level message
As far as I can tell, conversion to Python3 requires only a slight mod to CustomConsoleFormatter.init():
def __init__(self): super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%')
On Python 3.2.3:
tcsh-26: python3 demo_python_3.2.3.py 10: This is a DEBUG-level message 20: This is an INFO-level message
As you can see, my desire to replace '10' with 'DEBUG' is being thwarted.
I've tried digging around in Python3 source and it looks like the PercentStyle instantiation is clobbering self._fmt after I, well, clobber it myself.
My logging chops stop just short of being able to work around this wrinkle.
Can anyone recommend another way or perhaps point out what I'm overlooking?
stderr ) and a default format for the displayed message before delegating to the root logger to do the actual message output. You can change this by passing a format string to basicConfig() with the format keyword argument. For all options regarding how a format string is constructed, see Formatter Objects.
In Python, the built-in logging module can be used to log events. Log messages can have 5 levels - DEBUG, INGO, WARNING, ERROR and CRITICAL. They can also include traceback information for exceptions. Logs can be especially useful in case of errors to help identify their cause.
Logging in PythonYou can configure logging using the module and class functions or by creating a config file or a dictionary and loading it using fileConfig() or dictConfig() respectively. These are useful in case you want to change your logging configuration in a running application.
Python Logging Levels There are six log levels in Python; each level is associated with an integer that indicates the log severity: NOTSET=0, DEBUG=10, INFO=20, WARN=30, ERROR=40, and CRITICAL=50. All the levels are rather straightforward (DEBUG < INFO < WARN ) except NOTSET, whose particularity will be addressed next.
With a bit of digging, I was able to modify the Python 2 solution to work with Python 3. In Python2, it was necessary to temporarily overwrite Formatter._fmt
. In Python3, support for multiple format string types requires us to temporarily overwrite Formatter._style._fmt
instead.
# Custom formatter class MyFormatter(logging.Formatter): err_fmt = "ERROR: %(msg)s" dbg_fmt = "DBG: %(module)s: %(lineno)d: %(msg)s" info_fmt = "%(msg)s" def __init__(self): super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%') def format(self, record): # Save the original format configured by the user # when the logger formatter was instantiated format_orig = self._style._fmt # Replace the original format with one customized by logging level if record.levelno == logging.DEBUG: self._style._fmt = MyFormatter.dbg_fmt elif record.levelno == logging.INFO: self._style._fmt = MyFormatter.info_fmt elif record.levelno == logging.ERROR: self._style._fmt = MyFormatter.err_fmt # Call the original formatter class to do the grunt work result = logging.Formatter.format(self, record) # Restore the original format configured by the user self._style._fmt = format_orig return result
And here is Halloleo's example of how to use the above in your script (from the Python2 version of this question):
fmt = MyFormatter() hdlr = logging.StreamHandler(sys.stdout) hdlr.setFormatter(fmt) logging.root.addHandler(hdlr) logging.root.setLevel(logging.DEBUG)
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