diff options
Diffstat (limited to 'Python logging/index.md')
| -rw-r--r-- | Python logging/index.md | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/Python logging/index.md b/Python logging/index.md new file mode 100644 index 0000000..867dc20 --- /dev/null +++ b/Python logging/index.md @@ -0,0 +1,114 @@ +--- +created: 2024-03-17 +description: Python logging with ✨pretty colors🌸 +--- + +## Logging > print +Logging is useful, because all python code can use the same standard, allowing you to centrally control: + +- Which messages you wish to see + - Every debug message, for local development + - Disable debug messages, by changing 1 line e.g. for end user deployment +- How to format them + - Do you wish to see which module and line of code this message originated from +- Where they should end up + - Printed to [STDOUT](https://en.wikipedia.org/wiki/Standard_streams) (terminal) + - A log file + - A log server + - Maybe a notification should be triggered on CRITICAL errors + +> A python [*"module"*](https://docs.python.org/3/tutorial/modules.html) is simply just the name for a .py file. +> e.g. the file `database_handler.py` is a module called `database_handler` + +```py +import logging + + +class ColorFormatter(logging.Formatter): + grey = "\x1b[90;20m" + cyan = "\x1b[96;20m" + yellow = "\x1b[33;20m" + red = "\x1b[31;20m" + bold_red = "\x1b[31;1m" + reset = "\x1b[0m" + format = "%(asctime)s,%(msecs)03d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s" + + FORMATS = { + logging.DEBUG: grey + format + reset, + logging.INFO: cyan + format + reset, + logging.WARNING: yellow + format + reset, + logging.ERROR: red + format + reset, + logging.CRITICAL: bold_red + format + reset + } + + def format(self, record): + log_fmt = self.FORMATS.get(record.levelno) + formatter = logging.Formatter(log_fmt) + return formatter.format(record) + + +logger = logging.getLogger(__name__) # Instantiate a logger to be used in this module + +# Display every message Change this to INFO to see INFO and above (filter out DEBUG) +# See: https://docs.python.org/3/howto/logging.html#logging-levels +logger.root.setLevel(logging.DEBUG) + +stream_handler = logging.StreamHandler() # This catches and handles log messages on the root handler +stream_handler.setFormatter(ColorFormatter()) +logger.root.addHandler(stream_handler) + +logger.debug("debug message") +logger.info("info message") +logger.warning("warning message") +logger.error("error message") +logger.critical("critical message") +``` + +> Code snippet is modified, but based on: +> [stackoverflow.com - How can I color Python logging output?](https://stackoverflow.com/questions/384076/how-can-i-color-python-logging-output#answer-56944256). +> Used and credited as per [stackoverflow.com - CC BY-SA 4.0 content license](https://stackoverflow.com/help/licensing) + +<pre> +$ python /tmp/1.py +<span style="color:grey">2024-03-17 14:09:06,411,411 DEBUG [1.py:37] debug message</span> +<span style="color:var(--main-color)">2024-03-17 14:09:06,411,411 INFO [1.py:38] info message</span> +<span style="color:yellow">2024-03-17 14:09:06,411,411 WARNING [1.py:39] warning message</span> +<span style="color:red">2024-03-17 14:09:06,411,411 ERROR [1.py:40] error message</span> +<span style="font-weight: bold; color:red">2024-03-17 14:09:06,411,411 CRITICAL [1.py:41] critical message</span> +</pre> + + +In subsequent modules, do the following: +```py +import logging + +logger = logging.getLogger(__name__) # Set the logger name, to the name of the module + +logger.debug("debug message") +logger.info("info message") +logger.warning("warning message") +logger.error("error message") +logger.critical("critical message") +``` + +> Wish to change the colors? +> Color codes can be found here: [wikipedia.org - ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit) + +Okay, but why do we need to do it this way? + +Because logging is hieratical, these 2 loggers will be siblings under the root logger (see following tree structure). +Therefore we set a handler on the root logger which ensures all logging will hit our formatting code. + +<pre> +$ root +├── <span class="devicons devicons-python"></span> main +└── <span class="devicons devicons-python"></span> module_a +</pre> + +You can set a breakpoint and inspect `logger.parent` to see this structure: +```pycon +>>> logger.parent +<RootLogger root (DEBUG)> +``` + +Read more: [docs.python.org - Logging HOWTO](https://docs.python.org/3/howto/logging.html) |
