Skip to content

Instantly share code, notes, and snippets.

@taikedz
Last active November 21, 2024 09:24
Show Gist options
  • Save taikedz/7c156526602d905703ee31a9eee347db to your computer and use it in GitHub Desktop.
Save taikedz/7c156526602d905703ee31a9eee347db to your computer and use it in GitHub Desktop.
Python simple logger

Python Mini Logger

This post is opinionated.

Python's default log setup is useless ; it works against the "batteries included" approach we have come to expect.

When I want to write a log message, I want to know when, what level, and what message. I may want it on console, I may want it in a file.

This should be simple - but I end up every time having to look up how to create a full logging utility with custom file handling and string formatting. It should be as simple as logger = getLogger(), but the default behaviour for some unknown reason is to provide a completely useless formatting, and no shorthand for a sensible default.

That or I need to download some pip package of unknown provenance, trust that it hasn't been name-hijacked or doing some obfuscated exfilration.

External dependencies are the devil.

Sensible default

This utility allows for a single call with minimal configuration:

from minilog import SimpleLogger

LOG = SimpleLogger(name="mylog", level=SimpleLogger.INFO)

LOG.info("this is useful")

Which prints to console:

2024-11-20 10:43:44,567 | WARNING | mylog : this is useful

Simple MIT-licensed Code

  • The associated code in this gist can just be copied into your project, as-is.
  • It's MIT licensed which is equivalent for "do whatever you want".
  • It's extremely simple - you can review it yourself
  • It can't be name-hijacked - you keep your own copy, not an external dependency

License text included for reference.

Copyright (C) Tai Kedzierski
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the “Software”), to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# (C) Tai Kedzierski
# Provided under MIT license. Go wild.
import logging
class SimpleLogger(logging.Logger):
FORMAT_STRING = '%(asctime)s | %(levelname)s | %(name)s : %(message)s'
ERROR = logging.ERROR
WARN = logging.WARN
INFO = logging.INFO
DEBUG = logging.DEBUG
def __init__(self, name="main", fmt_string=FORMAT_STRING, level=logging.WARNING, console=True, files=None):
logging.Logger.__init__(self, name, level)
formatter_obj = logging.Formatter(fmt_string)
def _log_config(handler:logging.Handler, **kwargs):
handler = handler(**kwargs)
handler.setLevel(level)
handler.setFormatter(formatter_obj)
self.addHandler(handler)
if console is True:
_log_config(logging.StreamHandler, stream=sys.stdout)
if files is None:
files = []
if isinstance(files, str):
files = [files]
for filepath in files:
_log_config(logging.FileHandler, filename=filepath)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment