Robust and effective logging for Python 2 and 3.
Features
- Easy logging to console and/or (rotating) file.
- Provides a fully configured Python logger object.
- Pretty formatting, including level-specific colors in the console.
- JSON logging support (with integrated python-json-logger)
- Windows color output supported by colorama
- Robust against str/bytes encoding problems, works with all kinds of character encodings and special characters.
- Multiple loggers can write to the same logfile (also works across multiple Python files).
- Any directory structured mentioned is automatically created, if it doesn't exist.
- Global default logger with logzero.logger and custom loggers with logzero.setup_logger(..).
- Compatible with Python 2 and 3.
- All contained in a single file.
- Licensed under the MIT license.
- Heavily inspired by the Tornado web framework.
- Hosted on GitHub: https://github.com/metachris/logzero
Install logzero with pip:
$ pip install -U logzero
If you don't have pip installed, this Python installation guide can guide you through the process.
You can also install logzero from the public Github repo:
$ git clone https://github.com/metachris/logzero.git
$ cd logzero
$ python setup.py install
You can use logzero like this (logs only to the console by default):
from logzero import logger
logger.debug("hello")
logger.info("info")
logger.warning("warn")
logger.error("error")
# This is how you'd log an exception
try:
raise Exception("this is a demo exception")
except Exception as e:
logger.exception(e)
# JSON logging
import logzero
logzero.json()
logger.info("JSON test")
# Start writing into a logfile
logzero.logfile("/tmp/logzero-demo.log")
If this was a file called demo.py
, the output will look like this:
You can add logging to a (rotating) logfile like this:
import logzero
from logzero import logger
# non-rotating logfile
logzero.logfile("/tmp/logfile.log")
# rotating logfile
logzero.logfile("/tmp/rotating-logfile.log", maxBytes=1e6, backupCount=3)
# log messages
logger.info("This log message goes to the console and the logfile")
JSON logging can be enabled for the default logger with logzero.json(), or with setup_logger(json=True) for custom loggers:
# Configure the default logger to output JSON
>>> logzero.json()
>>> logger.info("test")
{"asctime": "2020-10-21 10:42:45,808", "filename": "<stdin>", "funcName": "<module>", "levelname": "INFO", "levelno": 20, "lineno": 1, "module": "<stdin>", "message": "test", "name": "logzero_default", "pathname": "<stdin>", "process": 76179, "processName": "MainProcess", "threadName": "MainThread"}
# Configure a custom logger to output JSON
>>> my_logger = setup_logger(json=True)
>>> my_logger.info("test")
{"asctime": "2020-10-21 10:42:45,808", "filename": "<stdin>", "funcName": "<module>", "levelname": "INFO", "levelno": 20, "lineno": 1, "module": "<stdin>", "message": "test", "name": "logzero_default", "pathname": "<stdin>", "process": 76179, "processName": "MainProcess", "threadName": "MainThread"}
The logged JSON object has these fields:
{
"asctime": "2020-10-21 10:43:40,765",
"filename": "test.py",
"funcName": "test_this",
"levelname": "INFO",
"levelno": 20,
"lineno": 9,
"module": "test",
"message": "info",
"name": "logzero",
"pathname": "_tests/test.py",
"process": 76204,
"processName": "MainProcess",
"threadName": "MainThread"
}
An exception logged with logger.exception(e) has these:
{
"asctime": "2020-10-21 10:43:25,193",
"filename": "test.py",
"funcName": "test_this",
"levelname": "ERROR",
"levelno": 40,
"lineno": 17,
"module": "test",
"message": "this is a demo exception",
"name": "logzero",
"pathname": "_tests/test.py",
"process": 76192,
"processName": "MainProcess",
"threadName": "MainThread",
"exc_info": "Traceback (most recent call last):\n File \"_tests/test.py\", line 15, in test_this\n raise Exception(\"this is a demo exception\")\nException: this is a demo exception"
}
Here are more examples which show how to use logfiles, custom formatters and setting a minimum loglevel.
Outcome | Method |
---|---|
Set a minimum log level | logzero.loglevel(..) |
Add logging to a logfile | logzero.logfile(..) |
Setup a rotating logfile | logzero.logfile(..) |
Disable logging to a logfile | logzero.logfile(None) |
JSON logging | logzero.json(...) |
Log to syslog | logzero.syslog(...) |
Use a custom formatter | logzero.formatter(..) |
import logging
import logzero
from logzero import logger
# This log message goes to the console
logger.debug("hello")
# Set a minimum log level
logzero.loglevel(logzero.INFO)
# Set a logfile (all future log messages are also saved there)
logzero.logfile("/tmp/logfile.log")
# Set a logfile (all future log messages are also saved there), but disable the default stderr logging
logzero.logfile("/tmp/logfile.log", disableStderrLogger=True)
# You can also set a different loglevel for the file handler
logzero.logfile("/tmp/logfile.log", loglevel=logzero.ERROR)
# Set a rotating logfile (replaces the previous logfile handler)
logzero.logfile("/tmp/rotating-logfile.log", maxBytes=1000000, backupCount=3)
# Disable logging to a file
logzero.logfile(None)
# Enable JSON log format
logzero.json()
# Disable JSON log format
logzero.json(False)
# Log to syslog, using default logzero logger and 'user' syslog facility
logzero.syslog()
# Log to syslog, using default logzero logger and 'local0' syslog facility
logzero.syslog(facility=SysLogHandler.LOG_LOCAL0)
# Set a custom formatter
formatter = logging.Formatter('%(name)s - %(asctime)-15s - %(levelname)s: %(message)s');
logzero.formatter(formatter)
# Log some variables
logger.info("var1: %s, var2: %s", var1, var2)
Instead of using the default logger you can also setup specific logger instances with logzero.setup_logger(..):
from logzero import setup_logger
logger1 = setup_logger(name="mylogger1")
logger2 = setup_logger(name="mylogger2", logfile="/tmp/test-logger2.log", level=logzero.INFO)
logger3 = setup_logger(name="mylogger3", logfile="/tmp/test-logger3.log", level=logzero.INFO, disableStderrLogger=True)
# Log something:
logger1.info("info for logger 1")
logger2.info("info for logger 2")
# log to a file only, excluding the default stderr logger
logger3.info("info for logger 3")
# JSON logging in a custom logger
jsonLogger = setup_logger(name="jsonLogger", json=True)
jsonLogger.info("info in json")
Since logzero uses the standard Python logger object, you can attach any Python logging handlers you can imagine!
This is how you add a SocketHandler:
import logzero
import logging
from logging.handlers import SocketHandler
# Setup the SocketHandler
socket_handler = SocketHandler(address=('localhost', logging.DEFAULT_TCP_LOGGING_PORT))
socket_handler.setLevel(logzero.DEBUG)
socket_handler.setFormatter(logzero.LogFormatter(color=False))
# Attach it to the logzero default logger
logzero.logger.addHandler(socket_handler)
# Log messages
logzero.logger.info("this is a test")
logzero.logger is an already set up standard Python logger instance for your convenience. You can use it from all your files and modules directly like this:
from logzero import logger
logger.debug("hello")
logger.info("info")
logger.warning("warning")
logger.error("error")
You can reconfigure the default logger globally with logzero.setup_default_logger(..).
See the documentation for the Python logger instance for more information about how you can use it.
.. autofunction:: logzero.loglevel
.. autofunction:: logzero.logfile
.. autofunction:: logzero.formatter
.. autofunction:: logzero.setup_logger
This is the default log format string:
DEFAULT_FORMAT = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s'
See also the Python LogRecord attributes you can use.
It is easy to use a custom formatter / a custom log format string:
- Define your log format string (you can use any of the LogRecord attributes).
- Create a Formatter object (based on logzero.LogFormatter to get all the encoding helpers).
- Supply the formatter object to the formatter argument in the setup_logger(..) method.
This is a working example on how to setup logging with a custom format:
import logzero
log_format = '%(color)s[%(levelname)1.1s %(asctime)s %(module)s:%(lineno)d]%(end_color)s %(message)s'
formatter = logzero.LogFormatter(fmt=log_format)
logzero.setup_default_logger(formatter=formatter)
All kinds of feedback and contributions are welcome.
- Create an issue
- Create a pull request
- https://github.com/metachris/logzero
- [email protected] // @metachris