From 40d5ae3ba6798bd2754963676681faeea229c1d6 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 15:34:26 +0200 Subject: [PATCH 01/13] Update README --- README.md | 54 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 7f78a02..76329fb 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ support Python 2.6 and above. * colorlog 5.x is an interim version that will warn Python 2 users to downgrade. * colorlog 4.x is the final version supporting Python 2. -[colorama] is included as a required dependency and initialised when using -colorlog on Windows. +[colorama] is included as a dependency on Windows, where it is automatically +initialised to support colored output. This library is over a decade old and supported a wide set of Python versions for most of its life, which has made it a difficult library to add new features @@ -53,14 +53,31 @@ logger = colorlog.getLogger('example') logger.addHandler(handler) ``` -The `ColoredFormatter` class takes several arguments: - -- `format`: The format string used to output the message (required). -- `datefmt`: An optional date format passed to the base class. See [`logging.Formatter`][Formatter]. -- `reset`: Implicitly adds a color reset code to the message output, unless the output already ends with one. Defaults to `True`. -- `log_colors`: A mapping of record level names to color names. The defaults can be found in `colorlog.default_log_colors`, or the below example. -- `secondary_log_colors`: A mapping of names to `log_colors` style mappings, defining additional colors that can be used in format strings. See below for an example. -- `style`: Available on Python 3.2 and above. See [`logging.Formatter`][Formatter]. +`ColoredFormatter` extends [`logging.Formatter`][Formatter] and accepts all of +its arguments. The only difference is `fmt`: if not provided, a default format +string is chosen based on `style` (e.g. +`%(log_color)s%(levelname)s:%(name)s:%(message)s` for `%` style). + +- `fmt`, `datefmt`, `style`, `validate`, `defaults`: + See [`logging.Formatter`][Formatter]. + +Additional arguments: + +- `reset`: Implicitly adds a color reset code to the message output, unless the + output already ends with one. Defaults to `True`. +- `log_colors`: A mapping of record level names to color names. The defaults + can be found in `colorlog.default_log_colors`, or the below example. +- `secondary_log_colors`: A mapping of names to `log_colors` style mappings, + defining additional colors that can be used in format strings. Defaults to + `None`. See below for an example. +- `stream`: The stream being written to (e.g. `sys.stderr`). Used to detect + whether the output is a TTY. Colors are disabled automatically on non-TTY + streams unless `force_color` is set. Defaults to `None`. +- `no_color`: Disable color output. Can also be set via the `NO_COLOR` + environment variable. Defaults to `False`. +- `force_color`: Force color output even on non-TTY streams. Takes precedence + over `no_color`. Can also be set via the `FORCE_COLOR` environment variable. + Defaults to `False`. Color escape codes can be selected based on the log records level, by adding parameters to the format string: @@ -86,7 +103,7 @@ The available color names are: - `red` - `green` - `yellow` -- `blue`, +- `blue` - `purple` - `cyan` - `white` @@ -103,6 +120,9 @@ support for these varies wildly across different terminals. - `light_cyan` - `light_white` +In addition to color names, you can use integers from 0 to 255 for 256-color +support (e.g. `fg_196`, `bg_42`). + ## Examples ![Example output](docs/example.png) @@ -114,18 +134,18 @@ using the default values for each argument. from colorlog import ColoredFormatter formatter = ColoredFormatter( - "%(log_color)s%(levelname)-8s%(reset)s %(blue)s%(message)s", + fmt="%(log_color)s%(levelname)s:%(name)s:%(message)s", datefmt=None, - reset=True, + style='%', log_colors={ - 'DEBUG': 'cyan', + 'DEBUG': 'white', 'INFO': 'green', 'WARNING': 'yellow', 'ERROR': 'red', - 'CRITICAL': 'red,bg_white', + 'CRITICAL': 'bold_red', }, - secondary_log_colors={}, - style='%' + reset=True, + secondary_log_colors={} ) ``` From ad8611f123a3bbde6c510b6bd5454966223aa312 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 15:34:26 +0200 Subject: [PATCH 02/13] Remove extra space --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76329fb..3289bd1 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Additional arguments: `None`. See below for an example. - `stream`: The stream being written to (e.g. `sys.stderr`). Used to detect whether the output is a TTY. Colors are disabled automatically on non-TTY - streams unless `force_color` is set. Defaults to `None`. + streams unless `force_color` is set. Defaults to `None`. - `no_color`: Disable color output. Can also be set via the `NO_COLOR` environment variable. Defaults to `False`. - `force_color`: Force color output even on non-TTY streams. Takes precedence From d212ddb31ecb7439a1a4c59bc368f6e94fb1d38f Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 15:34:26 +0200 Subject: [PATCH 03/13] Run mdformat --- README.md | 59 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 3289bd1..1ab2c35 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,17 @@ Add colours to the output of Python's `logging` module. -* [Source on GitHub](https://github.com/borntyping/python-colorlog) -* [Packages on PyPI](https://pypi.org/pypi/colorlog/) +- [Source on GitHub](https://github.com/borntyping/python-colorlog) +- [Packages on PyPI](https://pypi.org/pypi/colorlog/) ## Status -colorlog currently requires Python 3.6 or higher. Older versions (below 5.x.x) +colorlog currently requires Python 3.6 or higher. Older versions (below 5.x.x) support Python 2.6 and above. -* colorlog 6.x requires Python 3.6 or higher. -* colorlog 5.x is an interim version that will warn Python 2 users to downgrade. -* colorlog 4.x is the final version supporting Python 2. +- colorlog 6.x requires Python 3.6 or higher. +- colorlog 5.x is an interim version that will warn Python 2 users to downgrade. +- colorlog 4.x is the final version supporting Python 2. [colorama] is included as a dependency on Windows, where it is automatically initialised to support colored output. @@ -36,7 +36,7 @@ Install from PyPI with: pip install colorlog ``` -Several Linux distributions provide official packages ([Debian], [Arch], [Fedora], +Several Linux distributions provide official packages ([Debian], [Arch], [Fedora], [Gentoo], [OpenSuse] and [Ubuntu]), and others have user provided packages ([BSD ports], [Conda]). @@ -53,13 +53,13 @@ logger = colorlog.getLogger('example') logger.addHandler(handler) ``` -`ColoredFormatter` extends [`logging.Formatter`][Formatter] and accepts all of +`ColoredFormatter` extends [`logging.Formatter`][formatter] and accepts all of its arguments. The only difference is `fmt`: if not provided, a default format string is chosen based on `style` (e.g. `%(log_color)s%(levelname)s:%(name)s:%(message)s` for `%` style). - `fmt`, `datefmt`, `style`, `validate`, `defaults`: - See [`logging.Formatter`][Formatter]. + See [`logging.Formatter`][formatter]. Additional arguments: @@ -174,7 +174,7 @@ formatter = ColoredFormatter( ) ``` -### With [`dictConfig`][dictConfig] +### With [`dictConfig`][dictconfig] ```python logging.config.dictConfig({ @@ -189,7 +189,7 @@ logging.config.dictConfig({ A full example dictionary can be found in `tests/test_colorlog.py`. -### With [`fileConfig`][fileConfig] +### With [`fileConfig`][fileconfig] ```ini ... @@ -211,7 +211,7 @@ A full example configuration can be found in `tests/test_config.ini`. ### With custom log levels ColoredFormatter will work with custom log levels added with -[`logging.addLevelName`][addLevelName]: +[`logging.addLevelName`][addlevelname]: ```python import logging, colorlog @@ -272,23 +272,22 @@ 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. -[dictConfig]: http://docs.python.org/3/library/logging.config.html#logging.config.dictConfig -[fileConfig]: http://docs.python.org/3/library/logging.config.html#logging.config.fileConfig -[addLevelName]: https://docs.python.org/3/library/logging.html#logging.addLevelName -[Formatter]: http://docs.python.org/3/library/logging.html#logging.Formatter -[tox]: http://tox.readthedocs.org/ -[Arch]: https://archlinux.org/packages/extra/any/python-colorlog/ -[BSD ports]: https://www.freshports.org/devel/py-colorlog/ +[addlevelname]: https://docs.python.org/3/library/logging.html#logging.addLevelName +[arch]: https://archlinux.org/packages/extra/any/python-colorlog/ +[bsd ports]: https://www.freshports.org/devel/py-colorlog/ [colorama]: https://pypi.python.org/pypi/colorama -[Conda]: https://anaconda.org/conda-forge/colorlog -[Debian]: [https://packages.debian.org/buster/python3-colorlog](https://packages.debian.org/buster/python3-colorlog) -[Errbot]: http://errbot.io/ -[Fedora]: https://src.fedoraproject.org/rpms/python-colorlog -[Gentoo]: https://packages.gentoo.org/packages/dev-python/colorlog -[OpenSuse]: http://rpm.pbone.net/index.php3?stat=3&search=python-colorlog&srodzaj=3 -[Pythran]: https://github.com/serge-sans-paille/pythran -[Ubuntu]: https://launchpad.net/python-colorlog -[zenlog]: https://github.com/ManufacturaInd/python-zenlog -[structlog]: https://www.structlog.org/en/stable/ -[jsonlog]: https://github.com/borntyping/jsonlog +[conda]: https://anaconda.org/conda-forge/colorlog +[debian]: https://packages.debian.org/buster/python3-colorlog [dependents]: https://github.com/borntyping/python-colorlog/network/dependents?package_id=UGFja2FnZS01MDk3NDcyMQ%3D%3D +[dictconfig]: http://docs.python.org/3/library/logging.config.html#logging.config.dictConfig +[errbot]: http://errbot.io/ +[fedora]: https://src.fedoraproject.org/rpms/python-colorlog +[fileconfig]: http://docs.python.org/3/library/logging.config.html#logging.config.fileConfig +[formatter]: http://docs.python.org/3/library/logging.html#logging.Formatter +[gentoo]: https://packages.gentoo.org/packages/dev-python/colorlog +[jsonlog]: https://github.com/borntyping/jsonlog +[opensuse]: http://rpm.pbone.net/index.php3?stat=3&search=python-colorlog&srodzaj=3 +[pythran]: https://github.com/serge-sans-paille/pythran +[structlog]: https://www.structlog.org/en/stable/ +[ubuntu]: https://launchpad.net/python-colorlog +[zenlog]: https://github.com/ManufacturaInd/python-zenlog From f70a49e0031fdd3ccc94f331cc76bdcafe108ec4 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 15:34:26 +0200 Subject: [PATCH 04/13] Ensure lines contains 80 chars max --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1ab2c35..04ceb25 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ Install from PyPI with: pip install colorlog ``` -Several Linux distributions provide official packages ([Debian], [Arch], [Fedora], -[Gentoo], [OpenSuse] and [Ubuntu]), and others have user provided packages -([BSD ports], [Conda]). +Several Linux distributions provide official packages ([Debian], [Arch], +[Fedora], [Gentoo], [OpenSuse] and [Ubuntu]), and others have user provided +packages ([BSD ports], [Conda]). ## Usage @@ -83,7 +83,8 @@ Color escape codes can be selected based on the log records level, by adding parameters to the format string: - `log_color`: Return the color associated with the records level. -- `_log_color`: Return another color based on the records level if the formatter has secondary colors configured (see `secondary_log_colors` below). +- `_log_color`: Return another color based on the records level if the + formatter has secondary colors configured (see `secondary_log_colors` below). Multiple escape codes can be used at once by joining them with commas when configuring the color for a log level (but can't be used directly in the format @@ -93,7 +94,8 @@ text on a white background. The following escape codes are made available for use in the format string: - `{color}`, `fg_{color}`, `bg_{color}`: Foreground and background colors. -- `bold`, `bold_{color}`, `fg_bold_{color}`, `bg_bold_{color}`: Bold/bright colors. +- `bold`, `bold_{color}`, `fg_bold_{color}`, `bg_bold_{color}`: Bold/bright + colors. - `thin`, `thin_{color}`, `fg_thin_{color}`: Thin colors (terminal dependent). - `reset`: Clear all formatting (both foreground and background colors). From b5a211834ad5792a61e846e191ac6b5cee05d314 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 15:39:01 +0200 Subject: [PATCH 05/13] Update debian link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 04ceb25..cd24344 100644 --- a/README.md +++ b/README.md @@ -279,7 +279,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [bsd ports]: https://www.freshports.org/devel/py-colorlog/ [colorama]: https://pypi.python.org/pypi/colorama [conda]: https://anaconda.org/conda-forge/colorlog -[debian]: https://packages.debian.org/buster/python3-colorlog +[debian]: https://packages.debian.org/trixie/python3-colorlog [dependents]: https://github.com/borntyping/python-colorlog/network/dependents?package_id=UGFja2FnZS01MDk3NDcyMQ%3D%3D [dictconfig]: http://docs.python.org/3/library/logging.config.html#logging.config.dictConfig [errbot]: http://errbot.io/ From 8b1ed2d11a6284f7fc106adc9eec6f23a089bbaa Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 17:22:01 +0200 Subject: [PATCH 06/13] Update example --- README.md | 32 +++++++++++++++++++++----------- docs/example.png | Bin 10671 -> 17978 bytes docs/example.py | 23 ++++++++++++++++------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index cd24344..16405c1 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Add colours to the output of Python's `logging` module. - [Source on GitHub](https://github.com/borntyping/python-colorlog) -- [Packages on PyPI](https://pypi.org/pypi/colorlog/) +- [Package on PyPI](https://pypi.org/pypi/colorlog/) ## Status @@ -46,21 +46,24 @@ packages ([BSD ports], [Conda]). import colorlog handler = colorlog.StreamHandler() -handler.setFormatter(colorlog.ColoredFormatter( - '%(log_color)s%(levelname)s:%(name)s:%(message)s')) +handler.setFormatter(colorlog.ColoredFormatter()) logger = colorlog.getLogger('example') logger.addHandler(handler) ``` +### Arguments + `ColoredFormatter` extends [`logging.Formatter`][formatter] and accepts all of -its arguments. The only difference is `fmt`: if not provided, a default format -string is chosen based on `style` (e.g. -`%(log_color)s%(levelname)s:%(name)s:%(message)s` for `%` style). +its arguments: - `fmt`, `datefmt`, `style`, `validate`, `defaults`: See [`logging.Formatter`][formatter]. + The only difference is `fmt`: if not provided, a default format string is + chosen based on `style` (e.g. + `%(log_color)s%(levelname)s:%(name)s:%(message)s` for `%` style). + Additional arguments: - `reset`: Implicitly adds a color reset code to the message output, unless the @@ -79,6 +82,8 @@ Additional arguments: over `no_color`. Can also be set via the `FORCE_COLOR` environment variable. Defaults to `False`. +### Color escape codes + Color escape codes can be selected based on the log records level, by adding parameters to the format string: @@ -122,8 +127,8 @@ support for these varies wildly across different terminals. - `light_cyan` - `light_white` -In addition to color names, you can use integers from 0 to 255 for 256-color -support (e.g. `fg_196`, `bg_42`). +In addition to pre-defined color names, you can use integers from 0 to 255 for +256-color support (e.g. `fg_196`, `bg_42`). ## Examples @@ -139,15 +144,20 @@ formatter = ColoredFormatter( fmt="%(log_color)s%(levelname)s:%(name)s:%(message)s", datefmt=None, style='%', - log_colors={ + validate=True, + defaults=None, + reset=True, + log_colors={ 'DEBUG': 'white', 'INFO': 'green', 'WARNING': 'yellow', 'ERROR': 'red', 'CRITICAL': 'bold_red', }, - reset=True, - secondary_log_colors={} + secondary_log_colors=None, + stream=None, + no_color=False, + force_color=False ) ``` diff --git a/docs/example.png b/docs/example.png index aa8465f4379f998fb5fb11088a52acc8a7e82945..65ad5a4b991bfdd9d787154bb85159857b791973 100644 GIT binary patch literal 17978 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%0D2vXwd&w?i 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
  • k1dzZbU-*K*J zFeVoHz0-9F;`bXr%n^G;e@8&Ds1I}|v5+Vi>U*cipT7z=lbH?Qjte=i+jfQaZ|A9ZP;i%Qy9+IfI}*gBf0>bD80FF(EWMaH&*Z8rHdm2Pu4p@6m_KUs?#)S z48zQnnjluo>R`gtuTF|bCy^+@LH}zj-aVsG`|96yY3M!ha}<7LL)SvudljgV8Ua^= zA=>k_w2Xg(-v*%oNUIPEH3Z=i48fH`rV zHnJRlXq|Fi=iqNud?m~-Q^C9SE_|Uak%?|p>w?;`i3^nGg+cTCeDaG@jZnQ?VD1aW z8GmLPqJ+vqS&xJj6_pC>67S~U?*jqij~Kv17NV4*u40Xd-zxF7bH!0p`$+EGk@aq@ z6}(n*45A0RYKVBlJ!e8pek$#VZO1T|ir|LN7NW{5Pf-S&J?Pe(V=}iW=@`f_oK=@$ z|4%4VSCpc>=s|d}m)*qN0F9KTZCY|3*^MU?mb6lF^WV3`F_Xr51@PmfBJXg(8vX`c z2#VknfH1L;_7Zd)@M|vCK}f2u)jjs3U8q6S9?qT-5gi)`CCk+T8n|^dLp8coIHRSk zp~>^y^2K}FUvdXDGofP4=o^3VU2{`jRFt$B5b_69AqFGF-k?CY3^@u1y3vb|B^Eae zm}m1EHCCedc}DZ2DbB3k)`=!k zEen2brrTKEdQXdFr(XCjN?*JUgi6KgF5*}7l_N&A4?&c59=8mwqw*b`=Kr7`kR9+x zq=@IHo1LK0#sZTgW50hvkuUhz%oAv9kzy`##CRjJ^zzY&FwjZ3YE8G*1b2arUURKF zA*v2Ra%=8~ILvL0sa(zh8dCuWP7`|?LuMy&6t{&_Z?Y3sn`A&$*%KW47_UFT7;AQu zpgO)b;!>yUuqb(+$@7=E*`JL^)jQhItlz`Vh(~b%?fVq*-Y-{o*Y114e%GFl&U_8- zt-hZ+HYM7o(XAo19aEaBdtcI)**r=aoVfFEPLBI8%p}E

    yA0o=OCrUoAVWz80tO zoZ+U^EkiKaxJAW_Q9COC)f#+)ISbCIy}iD~Fd|9DCb*3=CYwDm1~A74a|RPyOg*MPt`J^2G~PjmXwHKFIA^3aNp@Rxj?sbAxDHwY zYO653rTuI^Nb+Rcf%Mb}1sJhJsKsj(J<~Tc3PP{{Pzr}`FummaGH7oQqIQEmG=L&W7jH_+Vt7>d&IK@TYEZA5i1ZodV;t%brQg7fM z{(bCHkuIJM=cvf0mh?cmuQ(eIE9We=7{kXmf0g=;aEcr_HHKp+I-&H7$+BH|$3t}S z68~jM-l!`K^)X}Nfo^NH%XHvZVdZZm%ME}ul6hSczG;Gw{*iTlASi|iE+3JrDs9J( zZJCUvGifT`&ps;)OXR+V7)k!8T0sUZI^*6R>P=I&uV-WxUZNG*l{*Z3aj}TutwL8e z21d_bXq8ezIXs6RlCK9>5qOk4MNv$+G2Q9$$3>mLZF{b{XqHd0Y2OD%%o!}J139le zKHM>3tmB&6K<*ltsc74IyhSIncTxJCslSUQ+Op(1)Sgm*SZ~yFJV`$iq2IUo1X|ER z!+tlID@mN1AL1|I z9U4s)bMkjWbtT&3=G-W|anlN6@DT)246%__h{(-8ov$%)pffVJ%yD~Rdc|dnG_;U7 zaEYbn8cWur#YpV@&1=X1OHHv#H0OKweOX6h-9}nw7r;imHVR zTu{W3pcv<}nV@%%Y+ZGKYmII#(&EU7CCN6Mn5}gtN9CwMC`7%trnz)r8PUNGGMa{+Ss@FNLIfpD?9s|(oWlg?Xq^` zw~Hki(DL+Id-_{j*s6$yp&o}|Z!eUpq-*?&n50NkqQ_q;5xrhZH;J;@ktpbF>H2Dr;uZvD>{5!vA-nC; zFPuso+U^-ebuq0a<*}q+N+Tj<+!|E5pyAOF@9UI!fQjx7=uL8Jr&C!h9P4qNNn?D5 z4dHm>8m#$!+aQz1A!PQPu>K9!#tx?gMhHGDalR#y+5LiD@D3~bTi&7+NKb!T|t?$2n*=nm58ycsS=1q$(GcS*|dDTv6+b9C{+px zE)^8mfPUyvONew*j-ivDdZd&+X94^R0{h%Zl3X{8&~R(2Z;w0^riYeE(WVRg diff --git a/docs/example.py b/docs/example.py index 5faf443..71cc600 100644 --- a/docs/example.py +++ b/docs/example.py @@ -6,18 +6,27 @@ def setup_logger(): - """Return a logger with a default ColoredFormatter.""" + """Return a logger with a ColoredFormatter using the default values for + each argument. + """ formatter = ColoredFormatter( - "%(log_color)s%(levelname)-8s%(reset)s %(blue)s%(message)s", + fmt="%(log_color)s%(levelname)s:%(name)s:%(message)s", datefmt=None, + style='%', + validate=True, + defaults=None, reset=True, log_colors={ - "DEBUG": "cyan", - "INFO": "green", - "WARNING": "yellow", - "ERROR": "red", - "CRITICAL": "red", + 'DEBUG': 'white', + 'INFO': 'green', + 'WARNING': 'yellow', + 'ERROR': 'red', + 'CRITICAL': 'bold_red', }, + secondary_log_colors=None, + stream=None, + no_color=False, + force_color=False ) logger = logging.getLogger("example") From 6bdda413867e6b0438f83e4362a3578ee2bb67b0 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 17:29:14 +0200 Subject: [PATCH 07/13] Small fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16405c1..aa15292 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ logger.addHandler(handler) its arguments: - `fmt`, `datefmt`, `style`, `validate`, `defaults`: - See [`logging.Formatter`][formatter]. + see [`logging.Formatter`][formatter]. The only difference is `fmt`: if not provided, a default format string is chosen based on `style` (e.g. From 87bb683e9a75a6f8f508f4ea07274004b519b939 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 17:33:12 +0200 Subject: [PATCH 08/13] Use double quotes in example --- README.md | 10 +++++----- docs/example.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index aa15292..22a40e5 100644 --- a/README.md +++ b/README.md @@ -148,11 +148,11 @@ formatter = ColoredFormatter( defaults=None, reset=True, log_colors={ - 'DEBUG': 'white', - 'INFO': 'green', - 'WARNING': 'yellow', - 'ERROR': 'red', - 'CRITICAL': 'bold_red', + "DEBUG": "white", + "INFO": "green", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "bold_red", }, secondary_log_colors=None, stream=None, diff --git a/docs/example.py b/docs/example.py index 71cc600..6fca78b 100644 --- a/docs/example.py +++ b/docs/example.py @@ -17,11 +17,11 @@ def setup_logger(): defaults=None, reset=True, log_colors={ - 'DEBUG': 'white', - 'INFO': 'green', - 'WARNING': 'yellow', - 'ERROR': 'red', - 'CRITICAL': 'bold_red', + "DEBUG": "white", + "INFO": "green", + "WARNING": "yellow", + "ERROR": "red", + "CRITICAL": "bold_red", }, secondary_log_colors=None, stream=None, From 24ec8b3f5ad8b142e4d1a5833d9370b3b8432bc7 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Mon, 22 Jun 2026 17:37:35 +0200 Subject: [PATCH 09/13] Fix secondary_log_colors default --- README.md | 4 ++-- docs/example.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 22a40e5..a56eec7 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Additional arguments: can be found in `colorlog.default_log_colors`, or the below example. - `secondary_log_colors`: A mapping of names to `log_colors` style mappings, defining additional colors that can be used in format strings. Defaults to - `None`. See below for an example. + `{}`. See below for an example. - `stream`: The stream being written to (e.g. `sys.stderr`). Used to detect whether the output is a TTY. Colors are disabled automatically on non-TTY streams unless `force_color` is set. Defaults to `None`. @@ -154,7 +154,7 @@ formatter = ColoredFormatter( "ERROR": "red", "CRITICAL": "bold_red", }, - secondary_log_colors=None, + secondary_log_colors={}, stream=None, no_color=False, force_color=False diff --git a/docs/example.py b/docs/example.py index 6fca78b..96836c9 100644 --- a/docs/example.py +++ b/docs/example.py @@ -23,7 +23,7 @@ def setup_logger(): "ERROR": "red", "CRITICAL": "bold_red", }, - secondary_log_colors=None, + secondary_log_colors={}, stream=None, no_color=False, force_color=False From a7cab167f6b5914e443f75e8b47888d2f9ae10d2 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Tue, 23 Jun 2026 11:56:20 +0200 Subject: [PATCH 10/13] Improve ColoredFormatter args doc --- README.md | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index a56eec7..4e759f9 100644 --- a/README.md +++ b/README.md @@ -54,33 +54,29 @@ logger.addHandler(handler) ### Arguments -`ColoredFormatter` extends [`logging.Formatter`][formatter] and accepts all of -its arguments: +`ColoredFormatter` extends [`logging.Formatter`][formatter] and accepts the +following arguments: -- `fmt`, `datefmt`, `style`, `validate`, `defaults`: - see [`logging.Formatter`][formatter]. - - The only difference is `fmt`: if not provided, a default format string is - chosen based on `style` (e.g. +- `fmt` *(default=`None`)*: A format string used to output the message. If + `None`, a default format string is selected based on `style` (e.g. `%(log_color)s%(levelname)s:%(name)s:%(message)s` for `%` style). - -Additional arguments: - -- `reset`: Implicitly adds a color reset code to the message output, unless the - output already ends with one. Defaults to `True`. -- `log_colors`: A mapping of record level names to color names. The defaults - can be found in `colorlog.default_log_colors`, or the below example. -- `secondary_log_colors`: A mapping of names to `log_colors` style mappings, - defining additional colors that can be used in format strings. Defaults to - `{}`. See below for an example. -- `stream`: The stream being written to (e.g. `sys.stderr`). Used to detect - whether the output is a TTY. Colors are disabled automatically on non-TTY - streams unless `force_color` is set. Defaults to `None`. -- `no_color`: Disable color output. Can also be set via the `NO_COLOR` - environment variable. Defaults to `False`. -- `force_color`: Force color output even on non-TTY streams. Takes precedence - over `no_color`. Can also be set via the `FORCE_COLOR` environment variable. - Defaults to `False`. +- `datefmt`, `style`, `validate`, `defaults`: see + [`logging.Formatter`][formatter]. +- `reset` *(default=`True`)*: Implicitly adds a color reset code to the + message output, unless the output already ends with one. +- `log_colors` *(default=`None`)*: A mapping of record level names to color + names. If `None`, `colorlog.default_log_colors` is used (see example below). +- `secondary_log_colors` *(default=`None`)*: A mapping of names to `log_colors` + style mappings, defining additional colors that can be used in format strings. + If `None`, an empty mapping is used. +- `stream` *(default=`None`)*: The stream being written to (e.g. `sys.stderr`). + Used to detect whether the output is a TTY. Colors are disabled automatically + on non-TTY streams unless `force_color` is set. +- `no_color` *(default=`False`)*: Disable color output. Can also be set via the + `NO_COLOR` environment variable. +- `force_color` *(default=`False`)*: Force color output even on non-TTY streams. + Takes precedence over `no_color`. Can also be set via the `FORCE_COLOR` + environment variable. ### Color escape codes @@ -147,7 +143,7 @@ formatter = ColoredFormatter( validate=True, defaults=None, reset=True, - log_colors={ + log_colors={ "DEBUG": "white", "INFO": "green", "WARNING": "yellow", @@ -179,7 +175,7 @@ formatter = ColoredFormatter( "%(log_color)s%(levelname)-8s%(reset)s %(message_log_color)s%(message)s", secondary_log_colors={ 'message': { - 'ERROR': 'red', + 'ERROR': 'red', 'CRITICAL': 'red' } } From f9c61023ec636faecc66cc5a7e1c3010ed6fc7a3 Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Tue, 23 Jun 2026 12:18:08 +0200 Subject: [PATCH 11/13] Update examples --- README.md | 23 ++++++++--------------- docs/example.png | Bin 17978 -> 9876 bytes docs/example.py | 19 ++++--------------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 4e759f9..74b1856 100644 --- a/README.md +++ b/README.md @@ -130,33 +130,26 @@ In addition to pre-defined color names, you can use integers from 0 to 255 for ![Example output](docs/example.png) -The following code creates a `ColoredFormatter` for use in a logging setup, -using the default values for each argument. +The following snippet creates a `ColoredFormatter` for use in a logging setup, +with a custom format string and log colors: ```python from colorlog import ColoredFormatter formatter = ColoredFormatter( - fmt="%(log_color)s%(levelname)s:%(name)s:%(message)s", - datefmt=None, - style='%', - validate=True, - defaults=None, - reset=True, + "%(log_color)s%(levelname)-8s%(reset)s %(blue)s%(message)s", log_colors={ - "DEBUG": "white", + "DEBUG": "cyan", "INFO": "green", "WARNING": "yellow", "ERROR": "red", - "CRITICAL": "bold_red", - }, - secondary_log_colors={}, - stream=None, - no_color=False, - force_color=False + "CRITICAL": "red,bg_white", + } ) ``` +*See `docs/example.py` for full example script.* + ### Using `secondary_log_colors` Secondary log colors are a way to have more than one color that is selected diff --git a/docs/example.png b/docs/example.png index 65ad5a4b991bfdd9d787154bb85159857b791973..0104707432e70d5bdc8c0ff617ccc59b9b40068f 100644 GIT binary patch literal 9876 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%0D2vXwd&w?i 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 Date: Tue, 23 Jun 2026 14:53:24 +0200 Subject: [PATCH 12/13] Replace spaces with tab --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 74b1856..c3ca5fd 100644 --- a/README.md +++ b/README.md @@ -144,7 +144,7 @@ formatter = ColoredFormatter( "WARNING": "yellow", "ERROR": "red", "CRITICAL": "red,bg_white", - } + } ) ``` From 2a365bc606e2694764892c03e1e76c4eaddae6ff Mon Sep 17 00:00:00 2001 From: maxime-bc Date: Tue, 23 Jun 2026 15:07:55 +0200 Subject: [PATCH 13/13] Remove useless statement --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c3ca5fd..4be7b7f 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ following arguments: - `reset` *(default=`True`)*: Implicitly adds a color reset code to the message output, unless the output already ends with one. - `log_colors` *(default=`None`)*: A mapping of record level names to color - names. If `None`, `colorlog.default_log_colors` is used (see example below). + names. If `None`, `colorlog.default_log_colors` is used. - `secondary_log_colors` *(default=`None`)*: A mapping of names to `log_colors` style mappings, defining additional colors that can be used in format strings. If `None`, an empty mapping is used.