Enlighten: a progress bar you do not have to redirect anything for
Enlighten Progress Bar for Python Console Apps
At a glance
- What is it?
- Enlighten is a console progress bar library for Python whose whole selling point is that you keep writing to stdout and stderr exactly as before, with no redirection and no extra code, while the library intercepts the output and keeps the bars pinned above it. It is packaged for pip, RPM, Debian and Conda, and the version numbering has a wrinkle that tells you about the project's history.
- Who is it for?
- Adopt Enlighten if you are writing a long-running Python command that prints progress and log output, because it is the rare progress bar you can drop into existing code without changing the print statements, and because it disables itself automatically when the output is not a terminal, which keeps your CI logs clean.
- Can I use it commercially?
- Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 155 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What the problem is, and what Enlighten does about it
Enlighten Progress Bar is a console progress bar library for Python, and the main advantage of Enlighten is that it allows writing to stdout and stderr without any redirection or additional code. You just print or log as you normally would.
That sentence is the whole design, and it is a real problem being solved. A conventional progress bar owns the terminal: you have to route your prints through the bar object, or capture stdout and replay it, or accept that your output and your progress indicator fight for the same line. Every workaround has a cost, and the cost is usually that the application code changes.
Enlighten inverts it. The library takes over the terminal, and your ordinary prints are captured, buffered and re-emitted above the bar, which stays pinned at the bottom. The application does not know the bar exists.
The implementation relies on two libraries, and the dependency list is short enough to read in one go. blessed at 1.17.7 or newer is the terminal capability library, which is what lets the package work across terminals it was never tested on, and prefixed at 0.3.2 or newer handles the prefixing of output lines. There is also a conditional dependency on backports.functools-lru-cache for Python below 3.2, and a test dependency on mock for Python below 3.3, which are the kind of back-compat pins that survive in a project with a long history.
The primary language is Python, the licence is MPL-2.0, the default branch is main, and the homepage is the Read the Docs site at python-enlighten.readthedocs.io. The recent releases are 1.14.1 from 2025-03-10, 0.14.0 from 2025-03-09 and 1.13.0 from 2024-12-02, and the last push was on 2026-05-21 with the project not archived. The author is Avram Lubkin, and the copyright line in setup.py runs from 2017 to 2026.
The 1.14.1 and 0.14.0 pair is worth a moment. The 0.14.0 release came a day earlier than the 1.14.1, which is a sign that a version scheme changed between them and that the project shipped a release under the old scheme and then immediately re-released under the new one.
Managers, and the TTY check that decides everything
The API has two layers, and the lower one is the manager.
The first step is to create a manager. Managers handle output to the terminal and allow multiple progress bars to be displayed at the same time, and get_manager is used to get a Manager instance.
Then there is the behaviour that decides whether any of this happens. Managers will only display output when the output stream, sys.__stdout__ by default, is attached to a TTY. If the stream is not attached to a TTY, the manager instance returned will be disabled.
That single rule is what makes the library safe to drop into an existing program. If you run under a cron job, a CI job, a pipe, or redirect your output to a file, the manager is disabled, the bars do not draw, and your prints come out as ordinary lines. You do not have to guard your code with an isatty check, and you do not get escape sequences polluting a log file.
Note also which stream it is. The default is sys.__stdout__, the original standard output object, rather than sys.stdout. That distinction matters because a library that replaces sys.stdout with its own wrapper cannot see the real file descriptor any more, and it is the reason the check is reliable even after the library has taken over.
In most cases, a manager can be created like this:
import enlighten
manager = enlighten.get_manager()And if you need to use a different output stream, or override the defaults, the documentation for get_manager covers it. The presence of a documented escape hatch for the stream is what lets the library be used in a test harness or under a custom terminal.
The manager is also where the shutdown lives. The multi-bar example ends with manager.stop(), and that call is what restores the terminal to a normal state. If you do not call it, a process that exits with the bar still active can leave the terminal in a strange state, so the manager is effectively a resource you own for the duration of your program.
Counters, and the two output formats
For a basic progress bar, you invoke the Manager.counter method. The example is the shape you would expect:
import time
import enlighten
manager = enlighten.get_manager()
pbar = manager.counter(total=100, desc='Basic', unit='ticks')
for num in range(100):
time.sleep(0.1) # Simulate work
pbar.update()The description and unit arguments are what make a bar readable, and the update call is the only thing you need in the loop.
Additional progress bars can be created with additional calls to the Manager.counter method, and the two-bar example shows how the two advance at different rates:
manager = enlighten.get_manager()
ticks = manager.counter(total=100, desc='Ticks', unit='ticks')
tocks = manager.counter(total=20, desc='Tocks', unit='tocks')
for num in range(100):
time.sleep(0.1) # Simulate work
print(num)
ticks.update()
if not num % 5:
tocks.update()
manager.stop()The loop prints a number on every iteration, which is the point: the print goes to stdout as usual while the bars stay below it. Every fifth iteration updates the second counter, so the two bars track different work.
The Counter class has two output formats, progress bar and counter. The progress bar format is used when a total is not None and the count is less than the total. If neither of these conditions are met, the counter format is used.
So the format is chosen by state rather than by configuration. A bar with a known total shows a bar that fills up, and once the count reaches or passes the total, or if there was never a total, it becomes a plain count. That handles the awkward case where the work is not known in advance, and it also stops a bar from looking broken when it hits 100 percent and the loop continues for cleanup.
There is a context_manager example in the examples directory as well, and given the manager.stop() call at the end of the multi-bar example, a context manager form is the obvious way to guarantee the terminal is restored even if the body raises. The example list also includes a float counter, a multicoloured variant, prefixes, multiple_logging, multiprocessing_queues and an ftp_downloader, which is a decent survey of the cases people actually hit.
Packaging, and the breadth of distribution channels
The Installation section offers four channels, which is unusual for a Python library and tells you something about the audience.
Pip is first:
$ pip install enlightenThen RPM for Fedora and EL8, meaning RHEL and CentOS, with a note that the EPEL repositories must be configured:
$ dnf install python3-enlightenThen the Debian and Ubuntu package:
$ apt-get install python3-enlightenAnd then Conda:
$ conda install -c conda-forge enlightenThe badges in the README header back this up, with distribution packages for Fedora, EPEL, Debian, Ubuntu and Anaconda all listed alongside the platform badges for Linux, Windows, MacOS and BSD, and the supported Python versions and implementations shown from PyPI.
The practical reason to have RPM and DEB packages is that a Linux system administrator installing a tool for a script may not want to introduce pip into the picture, and a system package survives Python upgrades. For a library that tends to end up as a dependency of a larger system on a server, that is the right call.
The BSD badge is also worth noting, since it signals that the package is expected to work on the BSDs rather than only on the three major desktop systems.
The setup.py follows the older convention rather than a pyproject-based one. It reads the version with get_version from the package's own __init__.py and the long description with a readme helper, both coming from a setup_helpers module in the repository. The packages find excludes tests, examples and benchmarks from the distribution, and the test suite is declared as tests.
The classifiers say Development Status 5, Production/Stable, and Environment Console, which is the correct classification for a terminal-only package, and the licence classifier names the Mozilla Public License 2.0 explicitly.
The copyright header in setup.py carries the full MPL text, which is what file-level copyleft requires, and the project also ships a .readthedocs.yaml for the documentation build and a requirements_docs.txt for the doc dependencies.
The project structure, and the testing and benchmarking setup
The repository layout shows a package with a real engineering setup behind it.
There is enlighten/ for the package itself, examples/ for the runnable examples, doc/ for the Sphinx documentation, tests/ for the test suite, benchmarks/ for performance work, and setup.py, setup.cfg, setup_helpers.py, MANIFEST.in and requirements.txt at the top level. There is a tox.ini for running the suite across environments, a pylintrc for linting, and a .sourcery.yaml, which is a tool for refactoring Python source with pattern matching, so the project uses automated cleanup tooling as well as a linter.
The asv.conf.json file at the root is the Air Speed Velocity configuration, which is the benchmark framework for Python projects. So performance is measured rather than assumed, which for a package that redraws a terminal on every update is the right thing to have.
The .github/ directory holds the workflows, and the README shows a GitHub Actions badge for the tests alongside a Travis CI badge. Having both is a leftover from the migration, and the badge list also includes a Codecov coverage badge, so coverage is tracked.
The examples directory is the part to read first if you are evaluating. There is basic.py, context_manager.py, demo.py, floats.py, ftp_downloader.py, multicolored.py, multiple_logging.py, multiprocessing_queues.py and prefixes.py. Each of those names is a problem someone actually had. Floats is a counter with a non-integer step. Multicolored is coloured output. Multiple logging is your logger's output arriving while bars are on screen. Multiprocessing queues is the case where the progress comes from worker processes rather than the main loop. And prefixes is the case where your output already has a prefix, such as a timestamp or a level name, and the library has to handle it without mangling it.
That list is a better feature summary than any bullet in a changelog, because it tells you which awkward cases the library has been made to survive.
How to evaluate it, and what to check first
There are four things to consider.
First, whether you can live with the ownership model. Enlighten takes over the terminal, which is exactly what you want for a long-running command with a progress bar and a lot of logging, and exactly what you do not want in a library that is called from inside a larger application that also wants to own the terminal. The manager is the unit of ownership, so a program with two independent subsystems both wanting a progress bar is a case where you need to think about who owns the terminal. The multi-bar support helps when it is one manager, not when it is two.
Second, the TTY behaviour, and it cuts both ways. The automatic disabling when the stream is not a terminal is a genuine safety property, but it also means that in a CI log you will see plain lines and no progress information at all. If you want progress in a non-terminal context, that is a different tool.
Third, the interpreter floor. The dependency on backports.functools-lru-cache for Python below 3.2 and mock below 3.3 shows the project still supports old interpreters, but the classifiers list a modern set of Python versions and the current PyPI supported-versions badge is the authority. The long-standing support is a good sign for a package that gets installed as a transitive dependency on servers you do not control.
Fourth, the version scheme, which is unusual enough to mention. The recent releases include 1.14.1 and, a day earlier, 0.14.0. A project that renumbers its versions and ships both within a day of each other is a project mid-migration, and if you depend on it, pin the version rather than tracking the branch.
What you get is a library whose central design decision is that the progress bar adapts to your program rather than the other way round, with a two-layer API of managers and counters, a documented set of examples covering the awkward cases, and distribution packages for every major Linux ecosystem. The cost is that it owns the terminal while it is active, and you must call manager.stop() or use the context manager form.
Editorial conclusion
Adopt Enlighten if you are writing a long-running Python command that prints progress and log output, because it is the rare progress bar you can drop into existing code without changing the print statements, and because it disables itself automatically when the output is not a terminal, which keeps your CI logs clean. Do not adopt it inside a larger framework that also wants to own the terminal, and do not expect to see progress information in a non-interactive log, since a manager on a pipe produces plain output and no bar. Before you commit, make sure you call manager.stop() or use the context manager form so the terminal is restored, read the examples directory because its filenames are the real feature list, and pin a version rather than tracking the branch, given that the release history contains a 0.14.0 and a 1.14.1 within a day of each other.
Frequently asked questions
What is the Enlighten progress bar library?
It is a console progress bar library for Python whose main advantage is that it allows writing to stdout and stderr without any redirection or additional code, so you just print or log as you normally would. It is MPL-2.0 licensed, written by Avram Lubkin, and the last push to the repository was on 2026-05-21.
How do I install Enlighten?
With pip install enlighten, or from a system package: dnf install python3-enlighten on Fedora and EL8 with EPEL configured, apt-get install python3-enlighten on Debian and Ubuntu, or conda install -c conda-forge enlighten. The project publishes packages for Fedora, EPEL, Debian, Ubuntu and Anaconda.
What does enlighten.get_manager() do?
It returns a Manager instance that handles output to the terminal and allows multiple progress bars to be displayed at the same time. Managers only display output when the output stream, sys.__stdout__ by default, is attached to a TTY, so if the stream is not a TTY the manager returned will be disabled.
When does Enlighten show a bar and when does it show a counter?
The Counter class has two output formats. The progress bar format is used when a total is not None and the count is less than the total, and if neither of those conditions are met the counter format is used, so the format is chosen by state rather than configuration.
What does Enlighten depend on?
On blessed at 1.17.7 or newer for terminal capabilities and prefixed at 0.3.2 or newer for output prefixing, with a conditional dependency on backports.functools-lru-cache for Python below 3.2 and a test dependency on mock for Python below 3.3.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/rockhopper-technologies-enlighten)Was this useful?