coloredlogs: Colored terminal output for Python’s logging module¶
Welcome to the documentation of coloredlogs version 15.0.1! The following sections are available:
User documentation¶
The readme is the best place to start reading, it’s targeted at all users:
coloredlogs: Colored terminal output for Python’s logging module¶
The coloredlogs package enables colored terminal output for Python’s logging
module. The ColoredFormatter class inherits from logging.Formatter and uses
ANSI escape sequences to render your logging messages in color. It uses only
standard colors so it should work on any UNIX terminal. It’s currently tested
on Python 2.7, 3.5+ and PyPy (2 and 3). On Windows coloredlogs automatically
tries to enable native ANSI support (on up-to-date Windows 10 installations)
and falls back on using colorama (if installed). Here is a screen shot of the
demo that is printed when the command coloredlogs --demo
is executed:

Note that the screenshot above includes custom logging levels defined by my verboselogs package: if you install both coloredlogs and verboselogs it will Just Work (verboselogs is of course not required to use coloredlogs).
Installation¶
The coloredlogs package is available on PyPI which means installation should be as simple as:
$ pip install coloredlogs
There’s actually a multitude of ways to install Python packages (e.g. the per user site-packages directory, virtual environments or just installing system wide) and I have no intention of getting into that discussion here, so if this intimidates you then read up on your options before returning to these instructions 😉.
Optional dependencies¶
Native ANSI support on Windows requires an up-to-date Windows 10 installation. If this is not working for you then consider installing the colorama package:
$ pip install colorama
Once colorama is installed it will be used automatically.
Usage¶
Here’s an example of how easy it is to get started:
import coloredlogs, logging
# Create a logger object.
logger = logging.getLogger(__name__)
# By default the install() function installs a handler on the root logger,
# this means that log messages from your code and log messages from the
# libraries that you use will all show up on the terminal.
coloredlogs.install(level='DEBUG')
# If you don't want to see log messages from libraries, you can pass a
# specific logger object to the install() function. In this case only log
# messages originating from that logger will show up on the terminal.
coloredlogs.install(level='DEBUG', logger=logger)
# Some examples.
logger.debug("this is a debugging message")
logger.info("this is an informational message")
logger.warning("this is a warning message")
logger.error("this is an error message")
logger.critical("this is a critical message")
Format of log messages¶
The ColoredFormatter class supports user defined log formats so you can use any log format you like. The default log format is as follows:
%(asctime)s %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s
This log format results in the following output:
2015-10-23 03:32:22 peter-macbook coloredlogs.demo[30462] DEBUG message with level 'debug'
2015-10-23 03:32:23 peter-macbook coloredlogs.demo[30462] VERBOSE message with level 'verbose'
2015-10-23 03:32:24 peter-macbook coloredlogs.demo[30462] INFO message with level 'info'
...
You can customize the log format and styling using environment variables as well as programmatically, please refer to the online documentation for details.
Enabling millisecond precision¶
If you’re switching from logging.basicConfig() to coloredlogs.install() you may notice that timestamps no longer include milliseconds. This is because coloredlogs doesn’t output milliseconds in timestamps unless you explicitly tell it to. There are three ways to do that:
The easy way is to pass the milliseconds argument to coloredlogs.install():
coloredlogs.install(milliseconds=True)
This became supported in release 7.1 (due to #16).
Alternatively you can change the log format to include ‘msecs’:
%(asctime)s,%(msecs)03d %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s
Here’s what the call to coloredlogs.install() would then look like:
coloredlogs.install(fmt='%(asctime)s,%(msecs)03d %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s')
Customizing the log format also enables you to change the delimiter that separates seconds from milliseconds (the comma above). This became possible in release 3.0 which added support for user defined log formats.
If the use of
%(msecs)d
isn’t flexible enough you can instead add%f
to the date/time format, it will be replaced by the value of%(msecs)03d
. Support for the%f
directive was added to release 9.3 (due to #45).
Custom logging fields¶
The following custom log format fields are supported:
%(hostname)s
provides the hostname of the local system.%(programname)s
provides the name of the currently running program.%(username)s
provides the username of the currently logged in user.
When coloredlogs.install() detects that any of these fields are used in the format string the applicable logging.Filter subclasses are automatically registered to populate the relevant log record fields.
Changing text styles and colors¶
The online documentation contains an example of customizing the text styles and colors.
Colored output from cron¶
When coloredlogs is used in a cron job, the output that’s e-mailed to you by cron won’t contain any ANSI escape sequences because coloredlogs realizes that it’s not attached to an interactive terminal. If you’d like to have colors e-mailed to you by cron there are two ways to make it happen:
Modifying your crontab¶
Here’s an example of a minimal crontab:
MAILTO="your-email-address@here"
CONTENT_TYPE="text/html"
* * * * * root coloredlogs --to-html your-command
The coloredlogs
program is installed when you install the coloredlogs
Python package. When you execute coloredlogs --to-html your-command
it runs
your-command
under the external program script
(you need to have this
installed). This makes your-command
think that it’s attached to an
interactive terminal which means it will output ANSI escape sequences which
will then be converted to HTML by the coloredlogs
program. Yes, this is a
bit convoluted, but it works great :-)
Modifying your Python code¶
The ColoredCronMailer class provides a context manager that automatically
enables HTML output when the $CONTENT_TYPE
variable has been correctly set
in the crontab.
This requires my capturer package which you can install using pip install
'coloredlogs[cron]'
. The [cron]
extra will pull in capturer 2.4 or newer
which is required to capture the output while silencing it - otherwise you’d
get duplicate output in the emails sent by cron
.
The context manager can also be used to retroactively silence output that has already been produced, this can be useful to avoid spammy cron jobs that have nothing useful to do but still email their output to the system administrator every few minutes :-).
Contact¶
The latest version of coloredlogs is available on PyPI and GitHub. The online documentation is available on Read The Docs and includes a changelog. For bug reports please create an issue on GitHub. If you have questions, suggestions, etc. feel free to send me an e-mail at peter@peterodding.com.
API documentation¶
The following API documentation is automatically generated from the source code:
API documentation¶
The following documentation is based on the source code of version 15.0.1 of the coloredlogs package.
The most useful entry points into the documentation are
install()
, ColoredFormatter
and
enable_system_logging()
.
The coloredlogs
module¶
Colored terminal output for Python’s logging
module.
Getting started¶
The easiest way to get started is by importing coloredlogs
and calling
coloredlogs.install()
(similar to logging.basicConfig()
):
>>> import coloredlogs, logging
>>> coloredlogs.install(level='DEBUG')
>>> logger = logging.getLogger('some.module.name')
>>> logger.info("this is an informational message")
2015-10-22 19:13:52 peter-macbook some.module.name[28036] INFO this is an informational message
The install()
function creates a ColoredFormatter
that injects ANSI escape sequences into the log output.
Environment variables¶
The following environment variables can be used to configure the
coloredlogs
module without writing any code:
Environment variable | Default value | Type of value |
---|---|---|
$COLOREDLOGS_AUTO_INSTALL |
‘false’ | a boolean that controls whether
auto_install() is called |
$COLOREDLOGS_LOG_LEVEL |
‘INFO’ | a log level name |
$COLOREDLOGS_LOG_FORMAT |
DEFAULT_LOG_FORMAT |
a log format string |
$COLOREDLOGS_DATE_FORMAT |
DEFAULT_DATE_FORMAT |
a date/time format string |
$COLOREDLOGS_LEVEL_STYLES |
DEFAULT_LEVEL_STYLES |
see parse_encoded_styles() |
$COLOREDLOGS_FIELD_STYLES |
DEFAULT_FIELD_STYLES |
see parse_encoded_styles() |
If the environment variable $NO_COLOR is set (the value doesn’t matter, even
an empty string will do) then coloredlogs.install()
will take this as a
hint that colors should not be used (unless the isatty=True
override was
passed by the caller).
Examples of customization¶
Here we’ll take a look at some examples of how you can customize
coloredlogs
using environment variables.
About the defaults¶
Here’s a screen shot of the default configuration for easy comparison with the screen shots of the following customizations (this is the same screen shot that is shown in the introduction):

The screen shot above was taken from urxvt
which doesn’t support faint text
colors, otherwise the color of green used for debug messages would have
differed slightly from the color of green used for spam messages.
Apart from the faint style of the spam level, the default configuration of coloredlogs sticks to the eight color palette defined by the original ANSI standard, in order to provide a somewhat consistent experience across terminals and terminal emulators.
Available text styles and colors¶
Of course you are free to customize the default configuration, in this case you
can use any text style or color that you know is supported by your terminal.
You can use the humanfriendly --demo
command to try out the supported text
styles and colors:

Changing the log format¶
The simplest customization is to change the log format, for example:
$ export COLOREDLOGS_LOG_FORMAT='[%(hostname)s] %(asctime)s %(message)s'
$ coloredlogs --demo
[peter-mbp] 2018-01-14 15:45:44 message with level spam (5)
[peter-mbp] 2018-01-14 15:45:45 message with level debug (10)
[peter-mbp] 2018-01-14 15:45:46 message with level verbose (15)
[peter-mbp] 2018-01-14 15:45:47 message with level info (20)
[peter-mbp] 2018-01-14 15:45:48 message with level notice (25)
[peter-mbp] 2018-01-14 15:45:49 message with level warning (30)
[peter-mbp] 2018-01-14 15:45:50 message with level success (35)
[peter-mbp] 2018-01-14 15:45:51 message with level error (40)
[peter-mbp] 2018-01-14 15:45:52 message with level critical (50)
Here’s what that looks like in a terminal (I always work in terminals with a black background and white text):

Changing the date/time format¶
You can also change the date/time format, for example you can remove the date part and leave only the time:
$ export COLOREDLOGS_LOG_FORMAT='%(asctime)s - %(message)s'
$ export COLOREDLOGS_DATE_FORMAT='%H:%M:%S'
$ coloredlogs --demo
15:45:34 - message with level spam (5)
15:45:35 - message with level debug (10)
15:45:36 - message with level verbose (15)
15:45:37 - message with level info (20)
15:45:38 - message with level notice (25)
15:45:39 - message with level warning (30)
15:45:40 - message with level success (35)
15:45:41 - message with level error (40)
15:45:42 - message with level critical (50)
Here’s what it looks like in a terminal:

Changing the colors/styles¶
Finally you can customize the colors and text styles that are used:
$ export COLOREDLOGS_LOG_FORMAT='%(asctime)s - %(message)s'
$ export COLOREDLOGS_DATE_FORMAT='%H:%M:%S'
$ export COLOREDLOGS_FIELD_STYLES='' # no styles
$ export COLOREDLOGS_LEVEL_STYLES='spam=22;debug=28;verbose=34;notice=220;warning=202;success=118,bold;error=124;critical=background=red'
$ coloredlogs --demo
15:45:23 - message with level spam (5)
15:45:24 - message with level debug (10)
15:45:25 - message with level verbose (15)
15:45:26 - message with level info (20)
15:45:27 - message with level notice (25)
15:45:28 - message with level warning (30)
15:45:29 - message with level success (35)
15:45:30 - message with level error (40)
15:45:31 - message with level critical (50)
Here’s an explanation of the features used here:
- The numbers used in
$COLOREDLOGS_LEVEL_STYLES
demonstrate the use of 256 color mode (the numbers refer to the 256 color mode palette which is fixed). - The success level demonstrates the use of a text style (bold).
- The critical level demonstrates the use of a background color (red).
Of course none of this can be seen in the shell transcript quoted above, but take a look at the following screen shot:

Some notes about log levels¶
With regards to the handling of log levels, the coloredlogs
package
differs from Python’s logging
module in two aspects:
While the
logging
module uses the default logging levellogging.WARNING
, thecoloredlogs
package has always usedlogging.INFO
as its default log level.When logging to the terminal or system log is initialized by
install()
orenable_system_logging()
the effective level [1] of the selected logger [2] is compared against the requested level [3] and if the effective level is more restrictive than the requested level, the logger’s level will be set to the requested level (this happens inadjust_level()
). The reason for this is to work around a combination of design choices in Python’slogging
module that can easily confuse people who aren’t already intimately familiar with it:- All loggers are initialized with the level
logging.NOTSET
. - When a logger’s level is set to
logging.NOTSET
thegetEffectiveLevel()
method will fall back to the level of the parent logger. - The parent of all loggers is the root logger and the root logger has its
level set to
logging.WARNING
by default (after importing thelogging
module).
Effectively all user defined loggers inherit the default log level
logging.WARNING
from the root logger, which isn’t very intuitive for those who aren’t already familiar with the hierarchical nature of thelogging
module.By avoiding this potentially confusing behavior (see #14, #18, #21, #23 and #24), while at the same time allowing the caller to specify a logger object, my goal and hope is to provide sane defaults that can easily be changed when the need arises.
[1] Refer to
logging.Logger.getEffectiveLevel()
for details.[2] The logger that is passed as an argument by the caller or the root logger which is selected as a default when no logger is provided.
[3] The log level that is passed as an argument by the caller or the default log level
logging.INFO
when no level is provided.- All loggers are initialized with the level
Classes and functions¶
-
coloredlogs.
DEFAULT_LOG_LEVEL
= 20¶ The default log level for
coloredlogs
(logging.INFO
).
-
coloredlogs.
DEFAULT_LOG_FORMAT
= '%(asctime)s %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s'¶ The default log format for
ColoredFormatter
objects (a string).
-
coloredlogs.
DEFAULT_DATE_FORMAT
= '%Y-%m-%d %H:%M:%S'¶ The default date/time format for
ColoredFormatter
objects (a string).
-
coloredlogs.
CHROOT_FILES
= ['/etc/debian_chroot']¶ A list of filenames that indicate a chroot and contain the name of the chroot.
-
coloredlogs.
DEFAULT_FIELD_STYLES
= {'asctime': {'color': 'green'}, 'hostname': {'color': 'magenta'}, 'levelname': {'bold': True, 'color': 'black'}, 'name': {'color': 'blue'}, 'programname': {'color': 'cyan'}, 'username': {'color': 'yellow'}}¶ Mapping of log format names to default font styles.
-
coloredlogs.
DEFAULT_LEVEL_STYLES
= {'critical': {'bold': True, 'color': 'red'}, 'debug': {'color': 'green'}, 'error': {'color': 'red'}, 'info': {}, 'notice': {'color': 'magenta'}, 'spam': {'color': 'green', 'faint': True}, 'success': {'bold': True, 'color': 'green'}, 'verbose': {'color': 'blue'}, 'warning': {'color': 'yellow'}}¶ Mapping of log level names to default font styles.
-
coloredlogs.
DEFAULT_FORMAT_STYLE
= '%'¶ The default logging format style (a single character).
-
coloredlogs.
FORMAT_STYLE_PATTERNS
= {'$': '\\$(\\w+)|\\${(\\w+)}', '%': '%\\((\\w+)\\)[#0 +-]*\\d*(?:\\.\\d+)?[hlL]?[diouxXeEfFgGcrs%]', '{': '{(\\w+)[^}]*}'}¶ A dictionary that maps the style characters
%
,{
and$
(see the documentation of thelogging.Formatter
class in Python 3.2+) to strings containing regular expression patterns that can be used to parse format strings in the corresponding style:%
- A string containing a regular expression that matches a “percent conversion
specifier” as defined in the String Formatting Operations section of the
Python documentation. Here’s an example of a logging format string in this
format:
%(levelname)s:%(name)s:%(message)s
. {
- A string containing a regular expression that matches a “replacement field” as
defined in the Format String Syntax section of the Python documentation.
Here’s an example of a logging format string in this format:
{levelname}:{name}:{message}
. $
- A string containing a regular expression that matches a “substitution
placeholder” as defined in the Template Strings section of the Python
documentation. Here’s an example of a logging format string in this format:
$levelname:$name:$message
.
These regular expressions are used by
FormatStringParser
to introspect and manipulate logging format strings.
-
coloredlogs.
auto_install
()[source]¶ Automatically call
install()
when$COLOREDLOGS_AUTO_INSTALL
is set.The coloredlogs package includes a path configuration file that automatically imports the
coloredlogs
module and callsauto_install()
when the environment variable$COLOREDLOGS_AUTO_INSTALL
is set.This function uses
coerce_boolean()
to check whether the value of$COLOREDLOGS_AUTO_INSTALL
should be consideredTrue
.
-
coloredlogs.
install
(level=None, **kw)[source]¶ Enable colored terminal output for Python’s
logging
module.Parameters: - level – The default logging level (an integer or a string with a
level name, defaults to
DEFAULT_LOG_LEVEL
). - logger – The logger to which the stream handler should be attached (a
Logger
object, defaults to the root logger). - fmt – Set the logging format (a string like those accepted by
Formatter
, defaults toDEFAULT_LOG_FORMAT
). - datefmt – Set the date/time format (a string, defaults to
DEFAULT_DATE_FORMAT
). - style – One of the characters
%
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
). See the documentation of thelogging.Formatter
class in Python 3.2+. On older Python versions only%
is supported. - milliseconds –
True
to show milliseconds likelogging
does by default,False
to hide milliseconds (the default isFalse
, see #16). - level_styles – A dictionary with custom level styles (defaults to
DEFAULT_LEVEL_STYLES
). - field_styles – A dictionary with custom field styles (defaults to
DEFAULT_FIELD_STYLES
). - stream – The stream where log messages should be written to (a
file-like object). This defaults to
None
which meansStandardErrorHandler
is used. - isatty –
True
to use aColoredFormatter
,False
to use a normalFormatter
(defaults to auto-detection usingterminal_supports_colors()
). - reconfigure – If
True
(the default) multiple calls tocoloredlogs.install()
will each override the previous configuration. - use_chroot – Refer to
HostNameFilter
. - programname – Refer to
ProgramNameFilter
. - username – Refer to
UserNameFilter
. - syslog – If
True
thenenable_system_logging()
will be called without arguments (defaults toFalse
). The syslog argument may also be a number or string, in this case it is assumed to be a logging level which is passed on toenable_system_logging()
.
The
coloredlogs.install()
function is similar tologging.basicConfig()
, both functions take a lot of optional keyword arguments but try to do the right thing by default:If reconfigure is
True
(it is by default) and an existingStreamHandler
is found that is connected to eitherstdout
orstderr
the handler will be removed. This means that first callinglogging.basicConfig()
and then callingcoloredlogs.install()
will replace the stream handler instead of adding a duplicate stream handler. If reconfigure isFalse
and an existing handler is found no further steps are taken (to avoid installing a duplicate stream handler).A
StreamHandler
is created and connected to the stream given by the stream keyword argument (sys.stderr
by default). The stream handler’s level is set to the value of the level keyword argument.A
ColoredFormatter
is created if the isatty keyword argument allows it (or auto-detection allows it), otherwise a normalFormatter
is created. The formatter is initialized with the fmt and datefmt keyword arguments (or their computed defaults).The environment variable
$NO_COLOR
is taken as a hint by auto-detection that colors should not be used.HostNameFilter.install()
,ProgramNameFilter.install()
andUserNameFilter.install()
are called to enable the use of additional fields in the log format.If the logger’s level is too restrictive it is relaxed (refer to notes about log levels for details).
The formatter is added to the handler and the handler is added to the logger.
- level – The default logging level (an integer or a string with a
level name, defaults to
-
coloredlogs.
check_style
(value)[source]¶ Validate a logging format style.
Parameters: value – The logging format style to validate (any value). Returns: The logging format character (a string of one character). Raises: ValueError
when the given style isn’t supported.On Python 3.2+ this function accepts the logging format styles
%
,{
and$
while on older versions only%
is accepted (because older Python versions don’t support alternative logging format styles).
-
coloredlogs.
increase_verbosity
()[source]¶ Increase the verbosity of the root handler by one defined level.
Understands custom logging levels like defined by my
verboselogs
module.
-
coloredlogs.
decrease_verbosity
()[source]¶ Decrease the verbosity of the root handler by one defined level.
Understands custom logging levels like defined by my
verboselogs
module.
-
coloredlogs.
is_verbose
()[source]¶ Check whether the log level of the root handler is set to a verbose level.
Returns: True
if the root handler is verbose,False
if not.
-
coloredlogs.
get_level
()[source]¶ Get the logging level of the root handler.
Returns: The logging level of the root handler (an integer) or DEFAULT_LOG_LEVEL
(if no root handler exists).
-
coloredlogs.
set_level
(level)[source]¶ Set the logging level of the root handler.
Parameters: level – The logging level to filter on (an integer or string). If no root handler exists yet this automatically calls
install()
.
-
coloredlogs.
adjust_level
(logger, level)[source]¶ Increase a logger’s verbosity up to the requested level.
Parameters: - logger – The logger to change (a
Logger
object). - level – The log level to enable (a string or number).
This function is used by functions like
install()
,increase_verbosity()
andenable_system_logging()
to adjust a logger’s level so that log messages up to the requested log level are propagated to the configured output handler(s).It uses
logging.Logger.getEffectiveLevel()
to check whether logger propagates or swallows log messages of the requested level and sets the logger’s level to the requested level if it would otherwise swallow log messages.Effectively this function will “widen the scope of logging” when asked to do so but it will never “narrow the scope of logging”. This is because I am convinced that filtering of log messages should (primarily) be decided by handlers.
- logger – The logger to change (a
-
coloredlogs.
find_defined_levels
()[source]¶ Find the defined logging levels.
Returns: A dictionary with level names as keys and integers as values. Here’s what the result looks like by default (when no custom levels or level names have been defined):
>>> find_defined_levels() {'NOTSET': 0, 'DEBUG': 10, 'INFO': 20, 'WARN': 30, 'WARNING': 30, 'ERROR': 40, 'FATAL': 50, 'CRITICAL': 50}
-
coloredlogs.
level_to_number
(value)[source]¶ Coerce a logging level name to a number.
Parameters: value – A logging level (integer or string). Returns: The number of the log level (an integer). This function translates log level names into their numeric values..
-
coloredlogs.
find_level_aliases
()[source]¶ Find log level names which are aliases of each other.
Returns: A dictionary that maps aliases to their canonical name. Note
Canonical names are chosen to be the alias with the longest string length so that e.g.
WARN
is an alias forWARNING
instead of the other way around.Here’s what the result looks like by default (when no custom levels or level names have been defined):
>>> from coloredlogs import find_level_aliases >>> find_level_aliases() {'WARN': 'WARNING', 'FATAL': 'CRITICAL'}
-
coloredlogs.
parse_encoded_styles
(text, normalize_key=None)[source]¶ Parse text styles encoded in a string into a nested data structure.
Parameters: text – The encoded styles (a string). Returns: A dictionary in the structure of the DEFAULT_FIELD_STYLES
andDEFAULT_LEVEL_STYLES
dictionaries.Here’s an example of how this function works:
>>> from coloredlogs import parse_encoded_styles >>> from pprint import pprint >>> encoded_styles = 'debug=green;warning=yellow;error=red;critical=red,bold' >>> pprint(parse_encoded_styles(encoded_styles)) {'debug': {'color': 'green'}, 'warning': {'color': 'yellow'}, 'error': {'color': 'red'}, 'critical': {'bold': True, 'color': 'red'}}
-
coloredlogs.
find_hostname
(use_chroot=True)[source]¶ Find the host name to include in log messages.
Parameters: use_chroot – Use the name of the chroot when inside a chroot? (boolean, defaults to True
)Returns: A suitable host name (a string). Looks for
CHROOT_FILES
that have a nonempty first line (taken to be the chroot name). If none are found thensocket.gethostname()
is used as a fall back.
-
coloredlogs.
find_program_name
()[source]¶ Select a suitable program name to embed in log messages.
Returns: One of the following strings (in decreasing order of preference): - The base name of the currently running Python program or
script (based on the value at index zero of
sys.argv
). - The base name of the Python executable (based on
sys.executable
). - The string ‘python’.
- The base name of the currently running Python program or
script (based on the value at index zero of
-
coloredlogs.
find_username
()[source]¶ Find the username to include in log messages.
Returns: A suitable username (a string). On UNIX systems this uses the
pwd
module which meansroot
will be reported when sudo is used (as it should). If this fails (for example on Windows) thengetpass.getuser()
is used as a fall back.
-
coloredlogs.
replace_handler
(logger, match_handler, reconfigure)[source]¶ Prepare to replace a handler.
Parameters: - logger – Refer to
find_handler()
. - match_handler – Refer to
find_handler()
. - reconfigure –
True
if an existing handler should be replaced,False
otherwise.
Returns: A tuple of two values:
- The matched
Handler
object orNone
if no handler was matched. - The
Logger
to which the matched handler was attached or the logger given toreplace_handler()
.
- logger – Refer to
-
coloredlogs.
find_handler
(logger, match_handler)[source]¶ Find a (specific type of) handler in the propagation tree of a logger.
Parameters: Returns: A tuple of two values:
This function finds a logging handler (of the given type) attached to a logger or one of its parents (see
walk_propagation_tree()
). It uses the undocumentedhandlers
attribute to find handlers attached to a logger, however it won’t raise an exception if the attribute isn’t available. The advantages of this approach are:- This works regardless of whether
coloredlogs
attached the handler or other Python code attached the handler. - This will correctly recognize the situation where the given logger has no
handlers but
propagate
is enabled and the logger has a parent logger that does have a handler attached.
- This works regardless of whether
-
coloredlogs.
match_stream_handler
(handler, streams=[])[source]¶ Identify stream handlers writing to the given streams(s).
Parameters: Returns: True
if the handler is aStreamHandler
logging to the given stream(s),False
otherwise.This function can be used as a callback for
find_handler()
.
-
coloredlogs.
walk_propagation_tree
(logger)[source]¶ Walk through the propagation hierarchy of the given logger.
Parameters: logger – The logger whose hierarchy to walk (a Logger
object).Returns: A generator of Logger
objects.Note
This uses the undocumented
logging.Logger.parent
attribute to find higher level loggers, however it won’t raise an exception if the attribute isn’t available.
-
class
coloredlogs.
BasicFormatter
(fmt=None, datefmt=None)[source]¶ Log
Formatter
that supports%f
for millisecond formatting.This class extends
Formatter
to enable the use of%f
for millisecond formatting in date/time strings, to allow for the type of flexibility requested in issue #45.-
formatTime
(record, datefmt=None)[source]¶ Format the date/time of a log record.
Parameters: - record – A
LogRecord
object. - datefmt – A date/time format string (defaults to
DEFAULT_DATE_FORMAT
).
Returns: The formatted date/time (a string).
This method overrides
formatTime()
to set datefmt toDEFAULT_DATE_FORMAT
when the caller hasn’t specified a date format.When datefmt contains the token
%f
it will be replaced by the value of%(msecs)03d
(refer to issue #45 for use cases).- record – A
-
-
class
coloredlogs.
ColoredFormatter
(fmt=None, datefmt=None, style='%', level_styles=None, field_styles=None)[source]¶ Log
Formatter
that uses ANSI escape sequences to create colored logs.ColoredFormatter
inherits fromBasicFormatter
to enable the use of%f
for millisecond formatting in date/time strings.Note
If you want to use
ColoredFormatter
on Windows then you need to callenable_ansi_support()
. This is done for you when you callcoloredlogs.install()
.-
__init__
(fmt=None, datefmt=None, style='%', level_styles=None, field_styles=None)[source]¶ Initialize a
ColoredFormatter
object.Parameters: - fmt – A log format string (defaults to
DEFAULT_LOG_FORMAT
). - datefmt – A date/time format string (defaults to
None
, but see the documentation ofBasicFormatter.formatTime()
). - style – One of the characters
%
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
) - level_styles – A dictionary with custom level styles
(defaults to
DEFAULT_LEVEL_STYLES
). - field_styles – A dictionary with custom field styles
(defaults to
DEFAULT_FIELD_STYLES
).
Raises: Refer to
check_style()
.This initializer uses
colorize_format()
to inject ANSI escape sequences in the log format string before it is passed to the initializer of the base class.- fmt – A log format string (defaults to
-
colorize_format
(fmt, style='%')[source]¶ Rewrite a logging format string to inject ANSI escape sequences.
Parameters: - fmt – The log format string.
- style – One of the characters
%
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
).
Returns: The logging format string with ANSI escape sequences.
This method takes a logging format string like the ones you give to
logging.Formatter
and processes it as follows:- First the logging format string is separated into formatting directives versus surrounding text (according to the given style).
- Then formatting directives and surrounding text are grouped based on whitespace delimiters (in the surrounding text).
- For each group styling is selected as follows:
- If the group contains a single formatting directive that has a style defined then the whole group is styled accordingly.
- If the group contains multiple formatting directives that have styles defined then each formatting directive is styled individually and surrounding text isn’t styled.
As an example consider the default log format (
DEFAULT_LOG_FORMAT
):%(asctime)s %(hostname)s %(name)s[%(process)d] %(levelname)s %(message)s
The default field styles (
DEFAULT_FIELD_STYLES
) define a style for the name field but not for the process field, however because both fields are part of the same whitespace delimited token they’ll be highlighted together in the style defined for the name field.
-
format
(record)[source]¶ Apply level-specific styling to log records.
Parameters: record – A LogRecord
object.Returns: The result of logging.Formatter.format()
.This method injects ANSI escape sequences that are specific to the level of each log record (because such logic cannot be expressed in the syntax of a log format string). It works by making a copy of the log record, changing the msg field inside the copy and passing the copy into the
format()
method of the base class.
-
-
class
coloredlogs.
Empty
[source]¶ An empty class used to copy
LogRecord
objects without reinitializing them.
-
class
coloredlogs.
HostNameFilter
(use_chroot=True)[source]¶ Log filter to enable the
%(hostname)s
format.Python’s
logging
module doesn’t expose the system’s host name while I consider this to be a valuable addition. Fortunately it’s very easy to expose additional fields in format strings:filter()
simply sets thehostname
attribute of eachLogRecord
object it receives and this is enough to enable the use of the%(hostname)s
expression in format strings.You can install this log filter as follows:
>>> import coloredlogs, logging >>> handler = logging.StreamHandler() >>> handler.addFilter(coloredlogs.HostNameFilter()) >>> handler.setFormatter(logging.Formatter('[%(hostname)s] %(message)s')) >>> logger = logging.getLogger() >>> logger.addHandler(handler) >>> logger.setLevel(logging.INFO) >>> logger.info("Does it work?") [peter-macbook] Does it work?
Of course
coloredlogs.install()
does all of this for you :-).-
classmethod
install
(handler, fmt=None, use_chroot=True, style='%')[source]¶ Install the
HostNameFilter
on a log handler (only if needed).Parameters: - fmt – The log format string to check for
%(hostname)
. - style – One of the characters
%
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
). - handler – The logging handler on which to install the filter.
- use_chroot – Refer to
find_hostname()
.
If fmt is given the filter will only be installed if fmt uses the
hostname
field. If fmt is not given the filter is installed unconditionally.- fmt – The log format string to check for
-
__init__
(use_chroot=True)[source]¶ Initialize a
HostNameFilter
object.Parameters: use_chroot – Refer to find_hostname()
.
-
classmethod
-
class
coloredlogs.
ProgramNameFilter
(programname=None)[source]¶ Log filter to enable the
%(programname)s
format.Python’s
logging
module doesn’t expose the name of the currently running program while I consider this to be a useful addition. Fortunately it’s very easy to expose additional fields in format strings:filter()
simply sets theprogramname
attribute of eachLogRecord
object it receives and this is enough to enable the use of the%(programname)s
expression in format strings.Refer to
HostNameFilter
for an example of how to manually install these log filters.-
classmethod
install
(handler, fmt, programname=None, style='%')[source]¶ Install the
ProgramNameFilter
(only if needed).Parameters: - fmt – The log format string to check for
%(programname)
. - style – One of the characters
%
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
). - handler – The logging handler on which to install the filter.
- programname – Refer to
__init__()
.
If fmt is given the filter will only be installed if fmt uses the
programname
field. If fmt is not given the filter is installed unconditionally.- fmt – The log format string to check for
-
__init__
(programname=None)[source]¶ Initialize a
ProgramNameFilter
object.Parameters: programname – The program name to use (defaults to the result of find_program_name()
).
-
classmethod
-
class
coloredlogs.
UserNameFilter
(username=None)[source]¶ Log filter to enable the
%(username)s
format.Python’s
logging
module doesn’t expose the username of the currently logged in user as requested in #76. Given thatHostNameFilter
andProgramNameFilter
are already provided by coloredlogs it made sense to provideUserNameFilter
as well.Refer to
HostNameFilter
for an example of how to manually install these log filters.-
classmethod
install
(handler, fmt, username=None, style='%')[source]¶ Install the
UserNameFilter
(only if needed).Parameters: - fmt – The log format string to check for
%(username)
. - style – One of the characters
%
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
). - handler – The logging handler on which to install the filter.
- username – Refer to
__init__()
.
If fmt is given the filter will only be installed if fmt uses the
username
field. If fmt is not given the filter is installed unconditionally.- fmt – The log format string to check for
-
__init__
(username=None)[source]¶ Initialize a
UserNameFilter
object.Parameters: username – The username to use (defaults to the result of find_username()
).
-
classmethod
-
class
coloredlogs.
StandardErrorHandler
(level=0)[source]¶ A
StreamHandler
that gets the value ofsys.stderr
for each log message.The
StandardErrorHandler
class enables monkey patching of sys.stderr. It’s basically the same as thelogging._StderrHandler
class present in Python 3 but it will be available regardless of Python version. This handler is used bycoloredlogs.install()
to improve compatibility with the Python standard library.-
__init__
(level=0)[source]¶ Initialize a
StandardErrorHandler
object.
-
stream
¶ Get the value of
sys.stderr
(a file-like object).
-
-
class
coloredlogs.
FormatStringParser
(style='%')[source]¶ Shallow logging format string parser.
This class enables introspection and manipulation of logging format strings in the three styles supported by the
logging
module starting from Python 3.2 (%
,{
and$
).-
__init__
(style='%')[source]¶ Initialize a
FormatStringParser
object.Parameters: style – One of the characters %
,{
or$
(defaults toDEFAULT_FORMAT_STYLE
).Raises: Refer to check_style()
.
-
contains_field
(format_string, field_name)[source]¶ Get the field names referenced by a format string.
Parameters: format_string – The logging format string. Returns: A list of strings with field names.
-
get_field_names
(format_string)[source]¶ Get the field names referenced by a format string.
Parameters: format_string – The logging format string. Returns: A list of strings with field names.
-
get_grouped_pairs
(format_string)[source]¶ Group the results of
get_pairs()
separated by whitespace.Parameters: format_string – The logging format string. Returns: A list of lists of FormatStringToken
objects.
-
get_pairs
(format_string)[source]¶ Tokenize a logging format string and extract field names from tokens.
Parameters: format_string – The logging format string. Returns: A generator of FormatStringToken
objects.
-
-
class
coloredlogs.
FormatStringToken
[source]¶ A named tuple for the results of
FormatStringParser.get_pairs()
.-
name
¶ The field name referenced in text (a string). If text doesn’t contain a formatting directive this will be
None
.
-
text
¶ The text extracted from the logging format string (a string).
-
-
class
coloredlogs.
NameNormalizer
[source]¶ Responsible for normalizing field and level names.
-
__init__
()[source]¶ Initialize a
NameNormalizer
object.
-
normalize_name
(name)[source]¶ Normalize a field or level name.
Parameters: name – The field or level name (a string). Returns: The normalized name (a string). Transforms all strings to lowercase and resolves level name aliases (refer to
find_level_aliases()
) to their canonical name:>>> from coloredlogs import NameNormalizer >>> from humanfriendly import format_table >>> nn = NameNormalizer() >>> sample_names = ['DEBUG', 'INFO', 'WARN', 'WARNING', 'ERROR', 'FATAL', 'CRITICAL'] >>> print(format_table([(n, nn.normalize_name(n)) for n in sample_names])) ----------------------- | DEBUG | debug | | INFO | info | | WARN | warning | | WARNING | warning | | ERROR | error | | FATAL | critical | | CRITICAL | critical | -----------------------
-
normalize_keys
(value)[source]¶ Normalize the keys of a dictionary using
normalize_name()
.Parameters: value – The dictionary to normalize. Returns: A dictionary with normalized keys.
-
get
(normalized_dict, name)[source]¶ Get a value from a dictionary after normalizing the key.
Parameters: - normalized_dict – A dictionary produced by
normalize_keys()
. - name – A key to normalize and get from the dictionary.
Returns: The value of the normalized key (if any).
- normalized_dict – A dictionary produced by
-
The coloredlogs.converter
module¶
Convert text with ANSI escape sequences to HTML.
-
coloredlogs.converter.
capture
(command, encoding='UTF-8')[source]¶ Capture the output of an external command as if it runs in an interactive terminal.
Parameters: - command – The command name and its arguments (a list of strings).
- encoding – The encoding to use to decode the output (a string).
Returns: The output of the command.
This function runs an external command under
script
(emulating an interactive terminal) to capture the output of the command as if it was running in an interactive terminal (including ANSI escape sequences).
-
coloredlogs.converter.
convert
(text, code=True, tabsize=4)[source]¶ Convert text with ANSI escape sequences to HTML.
Parameters: - text – The text with ANSI escape sequences (a string).
- code – Whether to wrap the returned HTML fragment in a
<code>...</code>
element (a boolean, defaults toTrue
). - tabsize – Refer to
str.expandtabs()
for details.
Returns: The text converted to HTML (a string).
-
coloredlogs.converter.
encode_whitespace
(text, tabsize=4)[source]¶ Encode whitespace so that web browsers properly render it.
Parameters: - text – The plain text (a string).
- tabsize – Refer to
str.expandtabs()
for details.
Returns: The text converted to HTML (a string).
The purpose of this function is to encode whitespace in such a way that web browsers render the same whitespace regardless of whether ‘preformatted’ styling is used (by wrapping the text in a
<pre>...</pre>
element).Note
While the string manipulation performed by this function is specifically intended not to corrupt the HTML generated by
convert()
it definitely does have the potential to corrupt HTML from other sources. You have been warned :-).
-
coloredlogs.converter.
encode_whitespace_cb
(match)[source]¶ Replace runs of multiple spaces with non-breaking spaces.
Parameters: match – A regular expression match object. Returns: The replacement string. This function is used by func:encode_whitespace() as a callback for replacement using a regular expression pattern.
-
coloredlogs.converter.
html_encode
(text)[source]¶ Encode characters with a special meaning as HTML.
Parameters: text – The plain text (a string). Returns: The text converted to HTML (a string).
-
coloredlogs.converter.
parse_hex_color
(value)[source]¶ Convert a CSS color in hexadecimal notation into its R, G, B components.
Parameters: value – A CSS color in hexadecimal notation (a string like ‘#000000’). Returns: A tuple with three integers (with values between 0 and 255) corresponding to the R, G and B components of the color. Raises: ValueError
on values that can’t be parsed.
-
coloredlogs.converter.
select_text_color
(r, g, b)[source]¶ Choose a suitable color for the inverse text style.
Parameters: - r – The amount of red (an integer between 0 and 255).
- g – The amount of green (an integer between 0 and 255).
- b – The amount of blue (an integer between 0 and 255).
Returns: A CSS color in hexadecimal notation (a string).
In inverse mode the color that is normally used for the text is instead used for the background, however this can render the text unreadable. The purpose of
select_text_color()
is to make an effort to select a suitable text color. Based on http://stackoverflow.com/a/3943023/112731.
-
class
coloredlogs.converter.
ColoredCronMailer
[source]¶ Easy to use integration between
coloredlogs
and the UNIXcron
daemon.By using
ColoredCronMailer
as a context manager in the command line interface of your Python program you make it trivially easy for users of your program to opt in to HTML output undercron
: The only thing the user needs to do is setCONTENT_TYPE="text/html"
in their crontab!Under the hood this requires quite a bit of magic and I must admit that I developed this code simply because I was curious whether it could even be done :-). It requires my
capturer
package which you can install usingpip install 'coloredlogs[cron]'
. The[cron]
extra will pull in thecapturer
2.4 or newer which is required to capture the output while silencing it - otherwise you’d get duplicate output in the emails sent bycron
.-
__init__
()[source]¶ Initialize output capturing when running under
cron
with the correct configuration.
-
__exit__
(exc_type=None, exc_value=None, traceback=None)[source]¶ Stop capturing output and convert the output to HTML (when applicable).
-
silence
()[source]¶ Tell
__exit__()
to swallow all output (things will be silent).This can be useful when a Python program is written in such a way that it has already produced output by the time it becomes apparent that nothing useful can be done (say in a cron job that runs every few minutes :-p). By calling
silence()
the output can be swallowed retroactively, avoiding useless emails fromcron
.
-
The coloredlogs.syslog
module¶
Easy to use UNIX system logging for Python’s logging
module.
Admittedly system logging has little to do with colored terminal output, however:
- The coloredlogs package is my attempt to do Python logging right and system logging is an important part of that equation.
- I’ve seen a surprising number of quirks and mistakes in system logging done
in Python, for example including
%(asctime)s
in a format string (the system logging daemon is responsible for adding timestamps and thus you end up with duplicate timestamps that make the logs awful to read :-). - The
%(programname)s
filter originated in my system logging code and I wanted it in coloredlogs so the step to include this module wasn’t that big. - As a bonus this Python module now has a test suite and proper documentation.
So there :-P. Go take a look at enable_system_logging()
.
-
coloredlogs.syslog.
LOG_DEVICE_MACOSX
= '/var/run/syslog'¶ The pathname of the log device on Mac OS X (a string).
-
coloredlogs.syslog.
LOG_DEVICE_UNIX
= '/dev/log'¶ The pathname of the log device on Linux and most other UNIX systems (a string).
-
coloredlogs.syslog.
DEFAULT_LOG_FORMAT
= '%(programname)s[%(process)d]: %(levelname)s %(message)s'¶ The default format for log messages sent to the system log (a string).
The
%(programname)s
format requiresProgramNameFilter
butenable_system_logging()
takes care of this for you.The
name[pid]:
construct (specifically the colon) in the format allows rsyslogd to extract the$programname
from each log message, which in turn allows configuration files in/etc/rsyslog.d/*.conf
to filter these log messages to a separate log file (if the need arises).
-
class
coloredlogs.syslog.
SystemLogging
(*args, **kw)[source]¶ Context manager to enable system logging.
-
__init__
(*args, **kw)[source]¶ Initialize a
SystemLogging
object.Parameters: - args – Positional arguments to
enable_system_logging()
. - kw – Keyword arguments to
enable_system_logging()
.
- args – Positional arguments to
-
-
coloredlogs.syslog.
enable_system_logging
(programname=None, fmt=None, logger=None, reconfigure=True, **kw)[source]¶ Redirect
logging
messages to the system log (e.g./var/log/syslog
).Parameters: - programname – The program name to embed in log messages (a string, defaults
to the result of
find_program_name()
). - fmt – The log format for system log messages (a string, defaults to
DEFAULT_LOG_FORMAT
). - logger – The logger to which the
SysLogHandler
should be connected (defaults to the root logger). - level – The logging level for the
SysLogHandler
(defaults toDEFAULT_LOG_LEVEL
). This value is coerced usinglevel_to_number()
. - reconfigure – If
True
(the default) multiple calls toenable_system_logging()
will each override the previous configuration. - kw – Refer to
connect_to_syslog()
.
Returns: A
SysLogHandler
object orNone
. If an existing handler is found and reconfigure isFalse
the existing handler object is returned. If the connection to the system logging daemon failsNone
is returned.As of release 15.0 this function uses
is_syslog_supported()
to check whether system logging is supported and appropriate before it’s enabled.Note
When the logger’s effective level is too restrictive it is relaxed (refer to notes about log levels for details).
- programname – The program name to embed in log messages (a string, defaults
to the result of
-
coloredlogs.syslog.
connect_to_syslog
(address=None, facility=None, level=None)[source]¶ Create a
SysLogHandler
.Parameters: - address – The device file or network address of the system logging
daemon (a string or tuple, defaults to the result of
find_syslog_address()
). - facility – Refer to
SysLogHandler
. Defaults toLOG_USER
. - level – The logging level for the
SysLogHandler
(defaults toDEFAULT_LOG_LEVEL
). This value is coerced usinglevel_to_number()
.
Returns: A
SysLogHandler
object orNone
(if the system logging daemon is unavailable).The process of connecting to the system logging daemon goes as follows:
The following two socket types are tried (in decreasing preference):
SOCK_RAW
avoids truncation of log messages but may not be supported.SOCK_STREAM
(TCP) supports longer messages than the default (which is UDP).
- address – The device file or network address of the system logging
daemon (a string or tuple, defaults to the result of
-
coloredlogs.syslog.
find_syslog_address
()[source]¶ Find the most suitable destination for system log messages.
Returns: The pathname of a log device (a string) or an address/port tuple as supported by SysLogHandler
.On Mac OS X this prefers
LOG_DEVICE_MACOSX
, after thatLOG_DEVICE_UNIX
is checked for existence. If both of these device files don’t exist the default used bySysLogHandler
is returned.
-
coloredlogs.syslog.
is_syslog_supported
()[source]¶ Determine whether system logging is supported.
Returns: True
if system logging is supported and can be enabled,False
if system logging is not supported or there are good reasons for not enabling it.The decision making process here is as follows:
- Override
- If the environment variable
$COLOREDLOGS_SYSLOG
is set it is evaluated usingcoerce_boolean()
and the resulting value overrides the platform detection discussed below, this allows users to override the decision making process if they disagree / know better. - Linux / UNIX
- On systems that are not Windows or MacOS (see below) we assume UNIX which means either syslog is available or sending a bunch of UDP packets to nowhere won’t hurt anyone…
- Microsoft Windows
- Over the years I’ve had multiple reports of coloredlogs spewing extremely verbose errno 10057 warning messages to the console (once for each log message I suppose) so I now assume it a default that “syslog-style system logging” is not generally available on Windows.
- Apple MacOS
There’s cPython issue #38780 which seems to result in a fatal exception when the Python interpreter shuts down. This is (way) worse than not having system logging enabled. The error message mentioned in #38780 has actually been following me around for years now, see for example:
- https://github.com/xolox/python-rotate-backups/issues/9 mentions Docker images implying Linux, so not strictly the same as #38780.
- https://github.com/xolox/python-npm-accel/issues/4 is definitely related
to #38780 and is what eventually prompted me to add the
is_syslog_supported()
logic.
-
coloredlogs.syslog.
match_syslog_handler
(handler)[source]¶ Identify system logging handlers.
Parameters: handler – The Handler
class to check.Returns: True
if the handler is aSysLogHandler
,False
otherwise.This function can be used as a callback for
find_handler()
.
Change log¶
The change log lists notable changes to the project:
Changelog¶
The purpose of this document is to list all of the notable changes to this project. The format was inspired by Keep a Changelog. This project adheres to semantic versioning.
- Release 15.0.1 (2021-06-11)
- Release 15.0 (2020-12-10)
- Release 14.3 (2020-12-10)
- Release 14.2 (2020-12-10)
- Release 14.1 (2020-12-10)
- Release 14.0 (2020-02-16)
- Release 12.0 (2020-02-16)
- Release 11.3 (2020-02-15)
- Release 11.2 (2020-02-15)
- Release 11.1 (2020-02-15)
- Release 11.0 (2020-02-14)
- Release 10.0 (2018-05-13)
- Release 9.3.1 (2018-04-30)
- Release 9.3 (2018-04-29)
- Release 9.2 (2018-04-27)
- Release 9.1 (2018-04-26)
- Release 9.0 (2018-01-17)
- Release 8.0 (2018-01-05)
- Release 7.3.3 (2018-01-05)
- Release 7.3.2 (2018-01-05)
- Release 7.3.1 (2017-11-23)
- Release 7.3 (2017-08-07)
- Release 7.2 (2017-08-07)
- Release 7.1 (2017-07-15)
- Release 7.0.1 (2017-07-15)
- Release 7.0 (2017-05-18)
- Release 6.4 (2017-05-17)
- Release 6.3 (2017-05-17)
- Release 6.2 (2017-05-17)
- Release 6.1 (2017-04-17)
- Release 6.0 (2017-03-10)
- Release 5.2 (2016-11-01)
- Release 5.1.1 (2016-10-10)
- Release 5.1 (2016-10-09)
- Release 5.0 (2015-11-14)
- Release 4.0 (2015-11-14)
- Release 3.5 (2015-11-13)
- Release 3.4 (2015-11-13)
- Release 3.3 (2015-11-13)
- Release 3.2 (2015-11-12)
- Release 3.1.4 (2015-10-31)
- Release 3.1.3 (2015-10-27)
- Release 3.1.2 (2015-10-24)
- Release 3.1.1 (2015-10-23)
- Release 3.1 (2015-10-23)
- Release 3.0 (2015-10-23)
- Release 2.0 (2015-10-14)
- Release 1.0.1 (2015-06-02)
- Release 1.0 (2015-05-27)
- Release 0.8 (2014-10-03)
- Release 0.7.1 (2014-10-02)
- Release 0.7 (2014-10-02)
- Release 0.6 (2014-09-21)
- Release 0.5 (2014-05-10)
- Release 0.4.9 (2014-05-03)
- Release 0.4.8 (2013-10-19)
- Release 0.4.7 (2013-09-29)
- Release 0.4.6 (2013-08-07)
- Release 0.4.5 (2013-08-07)
- Release 0.4.4 (2013-08-07)
- Release 0.4.3 (2013-07-21)
- Release 0.4.2 (2013-07-21)
- Release 0.4.1 (2013-07-20)
- Release 0.4 (2013-07-20)
- Release 0.3.1 (2013-07-01)
- Release 0.3 (2013-06-06)
- Release 0.2 (2013-05-31)
- Release 0.1 (2013-05-16)
Release 15.0.1 (2021-06-11)¶
Bug fix: Restore StandardErrorHandler
functionality
The StandardErrorHandler
class is responsible for dynamically
resolving (looking up the value of) sys.stderr for each logged message instead
of once when coloredlogs.install()
is called.
This was unintentionally broken by changes in release 14.1.
Release 15.0 (2020-12-10)¶
Don’t enable system logging on MacOS and Windows anymore.
This is backwards incompatible (which is why I’m bumping the major version
number) however the old behavior has been reported to be rather problematic
(see is_syslog_supported()
for details) so this
seems like the best choice.
Release 14.3 (2020-12-10)¶
Merged pull request #89 which enhances coloredlogs.install()
to
preserve the filters on handlers that are replaced by coloredlogs.
Release 14.2 (2020-12-10)¶
Honor the $NO_COLOR
environment variable as suggested in issue #88.
Release 14.1 (2020-12-10)¶
Bug fixes:
- Don’t allow interactive terminal detection to disable colored text when colored text is being forced by the caller (reported in issue #84).
- Automatically disable colored text when logging output is being redirected to a file in such a way that it actually works 😬 (reported in issue #100).
Other changes:
- Start testing on PyPy 3 (because why not?)
Release 14.0 (2020-02-16)¶
Integrate native Windows 10 support for ANSI escape sequences (#71, #72).
Native support for ANSI escape sequences was added to Windows 10 after its initial release, specifically in release 10.0.14393. I’ve now updated coloredlogs and humanfriendly to detect and enable this “new” native support.
Windows 10 seems to comprise the majority of Windows installations worldwide so in the interest of “looking forward” I’ve decided to drop the colorama requirement, given that it has now become a minority use case.
Hopefully most existing users will not experience any regression because they previously installed colorama already, and when available it will still be used. However new installations on older Windows systems now require users to install colorama separately. This has been documented in the readme in an attempt to minimize resulting confusion.
PS. In case anyone is wondering: I decided that giving a major Windows support update in coloredlogs the version 13.0 was asking for trouble, so I decided not to do that 😇.
Release 12.0 (2020-02-16)¶
Two backwards incompatible changes prompted another major version bump:
- Merged pull request #80 that drops support for Python 3.4 which has gone end-of-life and now represents less than 1% of PyPI downloads.
- Improved compatibility with the Python standard library by changing
the order of positional arguments received by the initializer of the
ColoredFormatter
class (as suggested in #64 and #75).
Release 11.3 (2020-02-15)¶
- Add support for the
%(username)s
field (requested in #76) and properly document supported custom fields. - Consistently use
console
highlighting in documentation. - Fix a broken link in the readme.
Release 11.2 (2020-02-15)¶
Merge pull request #79 which adds support for Python 3.8.
Release 11.1 (2020-02-15)¶
Starting with the previous release I’ve resolved to try and tackle the large number of open issues after an unplanned hiatus from the development and maintenance of my open source projects, so here are some more bug fixes:
Release 11.0 (2020-02-14)¶
This is a maintenance release that drops Python 2.6 support, adds Python 3.7 support and merges quite a few minor pull requests. The major version number was bumped because of the compatibility changes.
Merged pull requests:
- #58: Don’t import
coloredlogs
if$COLOREDLOGS_AUTO_INSTALL
is set but empty. - #60: Fix flake8 messages to help stabilize Travis CI builds.
- #61: Drop support for Python 2.6 to help stabilize Travis CI builds.
- #62: Use SVG badge in README for consistency.
- #69: Handle negative-offset timezones in tests.
- #70: Use
subprocess.check_call()
in the test suite to ensure that external commands succeed. - #74: Fix
TypeError
on MacOS on Python 3 in theconverter
module.
Other changes:
- Start testing on Python 3.7 (and document compatibility).
- Workaround Python 3.7 regression in test suite.
- Update
Makefile
to use Python 3 for local development. - Merge MacOS on Travis CI fixes from humanfriendly.
Release 10.0 (2018-05-13)¶
Proper format string parsing, support for style='{'
(#11, #17, #52).
Until now coloredlogs has required differently colored fields in logging format strings to be delimited by whitespace, leading to various issues:
- Back in December 2015 issue #11 was reported by someone who had expected to be able to style fields without whitespace in between differently.
- Until #52 was merged (released as 9.2 in April 2018) any whitespace would be collapsed to a single space, simply as a side effect of splitting on whitespace.
- This implementation was so naive that it didn’t support whitespace as a
padding character in
%()
formatting directives, because it wasn’t able to distinguish formatting directives from surrounding text.
In order to properly fix #11 I’m now introducing a very different approach that does distinguish formatting directives from their surrounding text, which means whitespace is no longer required. However in order to reduce the conceptual incompatibilities between the old versus new approach whitespace is still significant, as follows:
- First the logging format string is separated into formatting directives
versus surrounding text (which means whitespace used as a padding character
in a
%()
formatting directive is considered to be part of the formatting directive, as it should). - Then formatting directives and surrounding text are grouped based on whitespace delimiters (in the surrounding text).
- For each group styling is selected as follows:
- If the group contains a single formatting directive that has a style defined then the whole group is styled accordingly. This is the behavior which provides (some level of) conceptual backwards compatibility.
- If the group contains multiple formatting directives that have styles defined then each formatting directive is styled individually and surrounding text isn’t styled (this behavior is backwards incompatible but arguably an improvement over the old behavior).
While I was working on the improved format string parsing I figured it was
easiest to include support for style='{'
(requested in #17) from the
start in the new implementation, given that I was redoing the affected code
anyway.
Release 9.3.1 (2018-04-30)¶
Bug fix: Restore MacOS compatibility after publishing release 9.3.
The following build failure became apparent to me just minutes after publishing release 9.3 so I decided to change the implementation: https://travis-ci.org/xolox/python-coloredlogs/jobs/372806733
Release 9.3 (2018-04-29)¶
Enable flexible millisecond formatting using the %f
directive (#45).
Release 9.2 (2018-04-27)¶
- Merged pull request #47: Switch to
logging.getLogRecordFactory()
. In the merge commit I added a small performance enhancement by checking for the existence oflogging.getLogRecordFactory()
just once, when aColoredFormatter
object is instantiated. - Merged pull request #52: Don’t change whitespace in format strings. In the
merge commit I promoted the inline function to an instance method so that it
can be reused by sub classes of
ColoredFormatter
.
Release 9.1 (2018-04-26)¶
Release 9.0 (2018-01-17)¶
Added support for background colors and 256 color mode (#35).
Most of the changes required for this were actually implemented in the humanfriendly package (see issue #35). The changes in coloredlogs are mostly related to the ANSI to HTML conversion.
One unrelated change was made, that was to use faint green for the SPAM
log
level (to distinguish it from DEBUG
).
New features in ANSI to HTML conversion:
- Support for bright and faint colors.
- Support for underlined, strike-through and inverse text styles.
Bug fixes in ANSI to HTML conversion:
- The scheme of URLs is no longer stripped from visible output.
- Support for
\x1b[m
as a short hand for\x1b[0m
(I only learned about this today when I didn’t understand the empty ANSI escape sequence at the end of each line emitted byhg log
). - Ensure that the pattern for URLs doesn’t capture ANSI sequences.
- Documenting how it all works. This will follow in the next commit which is going to be a rather big one (hence why I see some value in keeping it separate from the implementation changes).
Miscellaneous changes:
- Add installation instructions to readme.
- Improve screenshots in documentation.
- Automate taking of screen shots :-).
Release 8.0 (2018-01-05)¶
Set the default date format in a new formatTime()
method (#42).
I decided to bump the major version number because this change is technically
backwards incompatible, even though it concerns a minor detail (datefmt
being set to its default value in the initializer). Then again, this change
does improve compatibility with the behavior of the logging.Formatter
class
in Python’s standard library, so there’s that :-).
Release 7.3.3 (2018-01-05)¶
Bug fix for coloredlogs --demo
so that it always displays the DEBUG
message (#41).
Release 7.3.2 (2018-01-05)¶
Bug fixes and improvements to ANSI to HTML conversion:
- Make sure that conversion of empty input produces no output.
- Strip bogus
^D
from output captured on MacOS. - Increase test coverage on MacOS via Travis CI.
Release 7.3.1 (2017-11-23)¶
Bug fix for get_install_requires()
in setup.py
script (fixes #43).
Release 7.3 (2017-08-07)¶
Added support for the SUCCESS
log level (related to #27 and verboselogs
issue #4).
Release 7.2 (2017-08-07)¶
Merged pull requests #34, #37 and #38:
- Include the files needed to generate the Sphinx documentation in source distributions published to PyPI (#34).
- Improve documentation by removing usage of deprecated
logger.warn()
function (#37). - Improve documentation by using module
__name__
variable for logger name (#38). - Also fixed the test suite after verboselogs 1.7 was released.
Release 7.1 (2017-07-15)¶
Make it easy to output milliseconds and improve documentation on this (#16).
Release 7.0.1 (2017-07-15)¶
Try to improve robustness during garbage collection (related to #33).
Release 7.0 (2017-05-18)¶
This release improves the robustness of ANSI to HTML conversion:
- Don’t break ANSI to HTML conversion on output encoding errors.
- Gracefully handle unsupported colors in converter module.
- Make it even easier to integrate with
cron
. - Improved the HTML encoding of whitespace.
- Wrap generated HTML in
<code>
by default. - Reduced the size of generated HTML (really CSS).
- Reduced internal duplication of constants.
Release 6.4 (2017-05-17)¶
Mention colorama.init()
in the documentation (fixes #25).
Release 6.3 (2017-05-17)¶
Bug fix: Avoid copy.copy()
deadlocks (fixes #29).
This was a rather obscure issue and I expect this not to to affect most users, but the reported breakage was definitely not intended, so it was a bug I wanted to fix.
Release 6.2 (2017-05-17)¶
Enable runtime patching of sys.stderr
(related to #30 and #31).
Release 6.1 (2017-04-17)¶
- Bug fix: Adjust logger level in
set_level()
,increase_verbosity()
, etc. (this is a follow up to release 6.0). - Bug fix: Never enable system logging on Windows.
- Increase test coverage (using mocking).
- Document Python 3.6 support.
Release 6.0 (2017-03-10)¶
Two backwards incompatible changes were made:
- Changed log level handling in
coloredlogs.install()
. - Changed the default system logging level from
DEBUG
toINFO
. To make it easier to restore the old behavior,coloredlogs.install(syslog='debug')
is now supported.
The old and problematic behavior was as follows:
coloredlogs.install()
would unconditionally change the log level of the root logger tologging.NOTSET
(changing it from the root logger’s default levellogging.WARNING
) and the log levels of handler(s) would control which log messages were actually emitted.enable_system_logging()
would never change the root logger’s log level, which meant that whenenable_system_logging()
was used in isolation frominstall()
the default log level would implicitly be set tologging.WARNING
(the default log level of the root logger).
Over the years I’ve gotten a lot of feedback about the log level handling in the coloredlogs package, it was clearly the number one cause of confusion for users. Here are some examples:
- https://github.com/xolox/python-coloredlogs/issues/14
- https://github.com/xolox/python-coloredlogs/issues/18
- https://github.com/xolox/python-coloredlogs/pull/21
- https://github.com/xolox/python-coloredlogs/pull/23
- https://github.com/xolox/python-coloredlogs/issues/24
My hope is that with the changes I’ve made in the past days, the experience for new users will be more ‘Do What I Mean’ and less ‘What The Fuck is Going On Here?!’ :-). Of course only time (and feedback, or lack thereof) will tell whether I’ve succeeded.
Release 5.2 (2016-11-01)¶
Merged pull request #19: Automatically call coloredlogs.install()
if
COLOREDLOGS_AUTO_INSTALL=true
.
While merging this pull request and writing tests for it I changed the implementation quite a bit from the original pull request:
- The environment variable was renamed from
COLOREDLOGS_AUTOUSE
toCOLOREDLOGS_AUTO_INSTALL
(in order to make it consistent with the other environment variables) and added to the documentation. - The
coloredlogs.pth
file was changed in order to reduce the amount of code required inside the*.pth
file as much as possible and create room to grow this feature if required, by extendingauto_install()
. I seriously dislike writing out complex code in a single line, especially when dealing with Python code :-). - The
coloredlogs.pth
file has been added toMANIFEST.in
to make sure thatpython setup.py sdist
copies the*.pth
file into the source distribution archives published to PyPI. - The
setup.py
script was changed to figure out the location of thelib/pythonX.Y/site-packages
directory using distutils instead of ‘hard coding’ the site-packages name (which I dislike for various reasons). - The
setup.py
script was changed to preserve compatibility with universal wheel distributions using what looks like an undocumented hack found through trial and error (the other hacks I found were much worse :-). I ran into this incompatibility when running the tests undertox
, which runspip install
under the hood, which in turn runspython setup.py bdist_wheel
under the hood to enable wheel caching.
Release 5.1.1 (2016-10-10)¶
- Starting from this release wheel distributions are published to PyPI.
- Refactored makefile and setup script (checkers, docs, wheels, twine, etc).
- Replaced
coloredlogs.readthedocs.org
withcoloredlogs.readthedocs.io
everywhere.
Release 5.1 (2016-10-09)¶
- Bug fix: Enable command capturing on MacOS (fixes #12).
- Add styles for the
SPAM
andNOTICE
levels added by my verboselogs package. - Set up automated MacOS tests on Travis CI.
- Documented Python 3.5 support.
Release 5.0 (2015-11-14)¶
- Remove
ColoredStreamHandler
and related functionality, thereby breaking backwards compatibility. - Remove Vim syntax script (impossible given user defined log formats :-).
- Improve test coverage.
Release 4.0 (2015-11-14)¶
Enable reconfiguration (also: get rid of global root handler).
Release 3.5 (2015-11-13)¶
- Bug fix: Never install duplicate syslog handlers.
- Added
walk_propagation_tree()
function (not useful in isolation :-). - Added
find_handler()
function (still not very useful in isolation).
Release 3.4 (2015-11-13)¶
Make it very easy to enable system logging.
Release 3.3 (2015-11-13)¶
Easy to use UNIX system logging?! I know this is unrelated to the name of this project - refer to the added documentation for more on that :-).
Release 3.2 (2015-11-12)¶
- Enable
%(programname)s
based onsys.argv[0]
. - Increase test coverage.
Release 3.1.4 (2015-10-31)¶
Bug fix: Don’t use bold font on Windows (follow up to previous change).
Release 3.1.3 (2015-10-27)¶
Bug fix: Don’t use bold font on Windows (not supported). For future reference, I found this issue here: https://ci.appveyor.com/project/xolox/pip-accel/build/1.0.15
Release 3.1.2 (2015-10-24)¶
Bug fix for log format colorization (fixes #9).
Rationale: I’m not validating the format, I just want to extract the referenced
field names, so looking for %(..)
without a trailing type specifier (and
optional modifiers) is fine here.
Release 3.1.1 (2015-10-23)¶
Fixed broken Colorama reference in README.rst
because it breaks the reStructuredText rendering on PyPI.
Release 3.1 (2015-10-23)¶
Depend on and use Colorama on Windows (as suggested in #2). I can’t actually test this because I don’t have access to a Windows system, but I guess some day someone will complain if this doesn’t work as intended ;-).
Release 3.0 (2015-10-23)¶
Major rewrite: Added ColoredFormatter
, deprecated ColoredStreamHandler
.
- Fixed #2 by switching from
connected_to_terminal()
toterminal_supports_colors()
(the latter understands enough about Windows to know it doesn’t support ANSI escape sequences). - Fixed #6 by adding support for user defined formats (even using a custom
filter to enable the use of
%(hostname)s
:-). - Fixed #7 by adding support for user defined formats and making
coloredlogs.install()
an almost equivalent oflogging.basicConfig()
.
This rewrite mostly resolves pip-accel issue #59. Basically all that’s
missing is a configuration option in pip-accel to make it easier to customize
the log format, although that can now be done by setting
$COLOREDLOGS_LOG_FORMAT
.
Release 2.0 (2015-10-14)¶
- Backwards incompatible: Change
ansi2html
tocoloredlogs --convert
(see #8). - Implement and enforce PEP-8 and PEP-257 compliance.
- Change Read the Docs links to use HTTPS.
- Move ad-hoc coverage configuration from
Makefile
to.coveragerc
.
Release 1.0.1 (2015-06-02)¶
- Bug fix for obscure
UnicodeDecodeError
insetup.py
(only on Python 3). - Document PyPy as a supported (tested) Python implementation.
Release 1.0 (2015-05-27)¶
- Move
coloredlogs.ansi_text()
tohumanfriendly.ansi_wrap()
. - Update
setup.py
to add trove classifiers and stop importing__version__
. - Start linking to Read the Docs as the project homepage.
Release 0.8 (2014-10-03)¶
- Merged pull request #5 which makes the severity to color mapping configurable.
- Added support for bold / faint / underline / inverse / strike through text styles. This extends the changes in pull request #5 into a generic severity ↔ color / style mapping and adds support for five text styles.
- Added a coverage badge to the readme.
Release 0.7.1 (2014-10-02)¶
Bug fix: Restore Python 3.4 compatibility.
Release 0.7 (2014-10-02)¶
- First stab at a proper test suite (already >= 90% coverage)
- Prepare to publish documentation on Read the Docs.
Release 0.6 (2014-09-21)¶
Added decrease_verbosity()
function (and simplify increase_verbosity()
).
Release 0.5 (2014-05-10)¶
- Merge pull request #4 adding Python 3 compatibility.
- Start using Travis CI (so I don’t accidentally drop Python 3 compatibility).
- Document supported Python versions (2.6, 2.7 & 3.4).
- Move demo code to separate
coloredlogs.demo
module.
Release 0.4.9 (2014-05-03)¶
Make the ansi2html
command a bit more user friendly.
Release 0.4.8 (2013-10-19)¶
Make it possible to use /etc/debian_chroot
instead of socket.gethostname()
.
Release 0.4.7 (2013-09-29)¶
Added is_verbose()
function (another easy shortcut :-).
Release 0.4.6 (2013-08-07)¶
Added increase_verbosity()
function (just an easy shortcut).
Release 0.4.5 (2013-08-07)¶
ColoredStreamHandler
now supports filtering on log level.
Release 0.4.4 (2013-08-07)¶
Bug fix: Protect against sys.stderr.isatty()
not being defined.
Release 0.4.3 (2013-07-21)¶
Change: Show the logger name by default.
Release 0.4.2 (2013-07-21)¶
Added coloredlogs.install()
function.
Release 0.4.1 (2013-07-20)¶
Bug fix for ansi2html
: Don’t leave typescript
files behind.
Release 0.4 (2013-07-20)¶
Added ansi2html
program to convert colored text to HTML.
Release 0.3.1 (2013-07-01)¶
Bug fix: Support Unicode format strings (issue #3).
Release 0.3 (2013-06-06)¶
Merge pull request #1: Refactor timestamp and name formatting into their own methods so callers can override the format. I made the following significant changes during merging:
- Added docstrings & mention subclassing in
README.md
- Don’t call
os.getpid()
when the result won’t be used. - Don’t call
render_*()
methods when results won’t be used.
Release 0.2 (2013-05-31)¶
- Change text styles (seems like an improvement to me)
- Integration with my just released verboselogs module.
- Improve the readme (with screenshots).
- Add PyPI link to
coloredlogs.py
. - Add URL to
setup.py
. - Vim syntax mode for colored logs!
Release 0.1 (2013-05-16)¶
Initial commit.