ENLIGHTEN(1)

πŸ“¦
version 1.11.2 Β· 3 versions
, in debian bookworm, debian trixie, ubuntu noble, ubuntu questing

πŸ’– ENLIGHTEN(1) πŸ’–

Enlighten β€” ok bestie, this is the manual page for enlighten, and it is genuinely a whole vibe ✨


πŸŽ€ NAME πŸŽ€

enlighten β€” Enlighten Documentation. that's it, that's the name, slay πŸ’…


πŸ“¦ PIP πŸ“¦

the easy way in, no cap:

$ pip install enlighten

πŸŒ€ RPM πŸŒ€

Fedora and EL8 (RHEL/CentOS)

heads up bestie: EPEL repositories must be configured for EL8 πŸ”₯

$ dnf install python3-enlighten

EL7 (RHEL/CentOS)

(EPEL repositories must be configured)

$ yum install python2-enlighten
$ yum install python36-enlighten

🐧 PKG 🐧

Arch Linux

btw i use arch 🫢

$ pacman -S python-enlighten

🌸 DEB 🌸

Debian and Ubuntu

$ apt-get install python3-enlighten

πŸ¦‹ CONDA πŸ¦‹

conda girlies, this one's for you:

$ conda install -c conda-forge enlighten

✨ BASIC ✨

okay so for a basic status bar you just invoke the Counter class directly. main character energy, no manager required πŸ’…

import time
import enlighten

pbar = enlighten.Counter(total=100, desc='Basic', unit='ticks')
for num in range(100):
    time.sleep(0.1)  # Simulate work
    pbar.update()

πŸ”₯ ADVANCED πŸ”₯

so if you wanna maintain multiple progress bars simultaneously, or write to the console while they're running, you need a manager. it's giving organization ✨

important caveat bestie: advanced output will only work when the output stream β€” sys.__stdout__ by default β€” is attached to a TTY. if it's not, it just quietly doesn't do the thing.

get_manager() is how you get a manager instance. it returns a disabled Manager instance if the stream isn't attached to a TTY, and an enabled instance if it is. so it just handles that for you, iconic πŸ’–

import time
import enlighten

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()

🌈 COUNTERS 🌈

the Counter class has two output formats, and they're both valid, periodt:

  • the progress bar format
  • the counter format

the progress bar format gets used when a total is not None and the count is less than the total. if neither of those conditions are met, you get the counter format instead. that's the whole rule, no cap πŸŽ€

import time
import enlighten

counter = enlighten.Counter(desc='Basic', unit='ticks')
for num in range(100):
    time.sleep(0.1)  # Simulate work
    counter.update()

🫢 STATUS BARS 🫢

status bars are bars that work similarly to progress similarly to progress bars and counters (yes bestie, the original says it like that, i'm not touching it 😭), but they present relatively static information. status bars are created with Manager.status_bar.

import enlighten
import time

manager = enlighten.get_manager()
status_bar = manager.status_bar('Static Message',
                                color='white_on_red',
                                justify=enlighten.Justify.CENTER)
time.sleep(1)
status_bar.update('Updated static message')
time.sleep(1)

status bars can also use formatting with dynamic variables, which is lowkey the best part:

import enlighten
import time

manager = enlighten.get_manager()
status_format = '{program}{fill}Stage: {stage}{fill} Status {status}'
status_bar = manager.status_bar(status_format=status_format,
                                color='bold_slategray',
                                program='Demo',
                                stage='Loading',
                                status='OKAY')
time.sleep(1)
status_bar.update(stage='Initializing', status='OKAY')
time.sleep(1)
status_bar.update(status='FAIL')

and status bars, like other bars, can be pinned πŸ“Œ

  • to pin a status bar to the top of all other bars, initialize it before any other bars.
  • to pin a bar to the bottom of the screen, use position=1 when initializing.

see StatusBar for more details πŸ‘‘


πŸ’… COLOR πŸ’…

status bars β€” and the bar component of a progress bar β€” can be colored by setting the color keyword argument. see Series Color for more info about valid colors 🎨

import time
import enlighten

counter = enlighten.Counter(total=100, desc='Colorized', unit='ticks', color='red')
for num in range(100):
    time.sleep(0.1)  # Simulate work
counter.update()

additionally, any part of the progress bar can be colored using counter formatting and the color capabilities of the underlying Blessed Terminal. this is where it gets highkey unhinged /pos πŸ’–

import enlighten

manager = enlighten.get_manager()

# Standard bar format
std_bar_format = u'{desc}{desc_pad}{percentage:3.0f}%|{bar}| ' + \
                 u'{count:{len_total}d}/{total:d} ' + \
                 u'[{elapsed}<{eta}, {rate:.2f}{unit_pad}{unit}/s]'

# Red text
bar_format = manager.term.red(std_bar_format)

# Red on white background
bar_format = manager.term.red_on_white(std_bar_format)

# X11 colors
bar_format = manager.term.peru_on_seagreen(std_bar_format)

# RBG text
bar_format = manager.term.color_rgb(2, 5, 128)(std_bar_format)

# RBG background
bar_format = manager.term.on_color_rgb(255, 190, 195)(std_bar_format)

# RGB text and background
bar_format = manager.term.on_color_rgb(255, 190, 195)(std_bar_format)
bar_format = manager.term.color_rgb(2, 5, 128)(bar_format)

# Apply color to select parts
bar_format = manager.term.red(u'{desc}') + u'{desc_pad}' + \
             manager.term.blue(u'{percentage:3.0f}%') + u'|{bar}|'

# Apply to counter
ticks = manager.counter(total=100, desc='Ticks', unit='ticks', bar_format=bar_format)
watch out bestie: if the color option is applied to a Counter, it will override any foreground color applied. so pick your fighter πŸ’€

🌈 MULTICOLORED 🌈

the bar component of a progress bar can be multicolored to track multiple categories in a single progress bar. it's giving stacked pride flag 🏳️🌈✨

the colors are drawn from right to left, in the order they were added. remember that, it matters.

by default, when multicolored progress bars are used, these additional fields are available for bar_format:

  • count_n (int) β€” Current value of count
  • count_0 (int) β€” Remaining count after deducting counts for all subcounters
  • count_00 (int) β€” Sum of counts from all subcounters
  • percentage_n (float) β€” Percentage complete
  • percentage_0 (float) β€” Remaining percentage after deducting percentages for all subcounters
  • percentage_00 (float) β€” Total of percentages from all subcounters

and when add_subcounter() is called with all_fields set to True, the subcounter gets these extra fields too:

  • eta_n (str) β€” Estimated time to completion
  • rate_n (float) β€” Average increments per second since parent was created

more info about bar_format lives in the Format section of the API 🫢

one use case for multicolored progress bars is recording the status of a series of tests. in this example, Failures are red, errors are white, and successes are green, and the count of each is listed right there in the progress bar. obsessed 😭

import random
import time
import enlighten

bar_format = u'{desc}{desc_pad}{percentage:3.0f}%|{bar}| ' + \
            u'S:{count_0:{len_total}d} ' + \
            u'F:{count_2:{len_total}d} ' + \
            u'E:{count_1:{len_total}d} ' + \
            u'[{elapsed}<{eta}, {rate:.2f}{unit_pad}{unit}/s]'

success = enlighten.Counter(total=100, desc='Testing', unit='tests',
                            color='green', bar_format=bar_format)
errors = success.add_subcounter('white')
failures = success.add_subcounter('red')

while success.count < 100:
    time.sleep(random.uniform(0.1, 0.3))  # Random processing time
    result = random.randint(0, 10)

    if result == 7:
        errors.update()
    if result in (5, 6):
        failures.update()
    else:
        success.update()

a more complicated example is recording process start-up. in this case, all items start red, transition to yellow, and eventually all will be green πŸ“ the count, percentage, rate, and eta fields are all derived from the second subcounter added. iykyk.

import random
import time
import enlighten

services = 100
bar_format = u'{desc}{desc_pad}{percentage_2:3.0f}%|{bar}|' + \
            u' {count_2:{len_total}d}/{total:d} ' + \
            u'[{elapsed}<{eta_2}, {rate_2:.2f}{unit_pad}{unit}/s]'

initializing = enlighten.Counter(total=services, desc='Starting', unit='services',
                                color='red', bar_format=bar_format)
starting = initializing.add_subcounter('yellow')
started = initializing.add_subcounter('green', all_fields=True)

while started.count < services:
    remaining = services - initializing.count
    if remaining:
        num = random.randint(0, min(4, remaining))
        initializing.update(num)

    ready = initializing.count - initializing.subcount
    if ready:
        num = random.randint(0, min(3, ready))
        starting.update_from(initializing, num)

    if starting.count:
        num = random.randint(0, min(2, starting.count))
        started.update_from(starting, num)

    time.sleep(random.uniform(0.1, 0.5))  # Random processing time

⭐ ADDITIONAL EXAMPLES ⭐

more content for the girlies, all of these are real:

  • Basic β€” Basic progress bar
  • Binary prefixes β€” Automatic binary prefixes
  • Context manager β€” Managers and counters as context managers
  • FTP downloader β€” Show progress downloading files from FTP
  • Floats β€” Support totals and counts that are floats
  • Multicolored β€” Multicolored progress bars
  • Multiple with logging β€” Nested progress bars and logging
  • Multiprocessing queues β€” Progress bars with queues for IPC

🎨 CUSTOMIZATION 🎨

Enlighten is highly configurable. for info on modifying the output, go look at the Series and Format sections of the Counter documentation πŸ’œ


πŸ”Œ ENABLE / DISABLE πŸ”Œ

a program may want to disable progress bars based on a config setting, as well as if output redirection occurs. very responsible of it honestly 🫢

import sys
import enlighten

# Example configuration object
config = {'stream': sys.stdout,
          'useCounter': False}

enableCounter = config['useCounter'] and stream.isatty()
manager = enlighten.Manager(stream=config['stream'], enabled=enableCounter)

and the get_manager() function slightly simplifies all of that:

import enlighten

# Example configuration object
config = {'stream': None,  # Defaults to sys.__stdout__
          'useCounter': False}

manager = enlighten.get_manager(stream=config['stream'], enabled=config['useCounter'])

🧚 CONTEXT MANAGERS 🧚

both Counter and Manager can be used as context managers. nesting them is so satisfying ngl ✨

import enlighten

SPLINES = 100

with enlighten.Manager() as manager:
    with manager.counter(total=SPLINES, desc='Reticulating:', unit='splines') as retic:
        for num in range(SPLINES + 1):
            retic.update()

✨ AUTOMATIC UPDATING ✨

Okay so both Counter and SubCounter instances can be called as functions on one or more iterators, and like… that's the whole magic trick πŸ’– A generator gets returned, it yields each element of the iterables, and then it bumps the count by 1. So cute, so efficient.

NOTE: When a Counter instance is called as a function, the type checking is lazy β€” it literally will not validate that an iterable was passed until iteration actually begins. It's giving "I'll deal with it later" energy πŸ™ˆ
import time
import enlighten

flock1 = ['Harry', 'Sally', 'Randy', 'Mandy', 'Danny', 'Joe']
flock2 = ['Punchy', 'Kicky', 'Spotty', 'Touchy', 'Brenda']
total = len(flock1) + len(flock2)

manager = enlighten.Manager()
pbar = manager.counter(total=total, desc='Counting Sheep', unit='sheep')

for sheep in pbar(flock1, flock2):
    time.sleep(0.2)
    print('%s: Baaa' % sheep)

🌸 USER-DEFINED FIELDS 🌸

Both Counter and StatusBar accept user-defined fields as keyword arguments β€” at initialization and during an update. Bestie, these fields are persistent, so you only have to specify them when they actually change. Lowkey genius.

In this next example, source is a user-defined field that gets periodically updated. Iconic.

import enlighten
import random
import time

bar_format = u'{desc}{desc_pad}{source} {percentage:3.0f}%|{bar}| ' + \
             u'{count:{len_total}d}/{total:d} ' + \
             u'[{elapsed}<{eta}, {rate:.2f}{unit_pad}{unit}/s]'
manager = enlighten.get_manager(bar_format=bar_format)

bar = manager.counter(total=100, desc='Loading', unit='files', source='server.a')
for num in range(100):
    time.sleep(0.1)  # Simulate work
    if not num % 5:
        bar.update(source=random.choice(['server.a', 'server.b', 'server.c']))
    else:
        bar.update()

For more info, go look at the Counter Format and StatusBar Format sections πŸ‘‘


πŸ¦‹ HUMAN-READABLE NUMERIC PREFIXES πŸ¦‹

Enlighten supports automatic SI (metric) and IEC (binary) prefixes using the Prefixed library. Obsessed.

All rate and interval formatting fields are of the type prefixed.Float. Meanwhile total and all count fields default to int. But here's the tea: if total or or count are set to a float, or a float gets provided to update(), these fields become prefixed.Float instead. Slay πŸ’…

import time
import random
import enlighten

size = random.uniform(1.0, 10.0) * 2 ** 20  # 1-10 MiB (float)
chunk_size = 64 * 1024  # 64 KiB

bar_format = '{desc}{desc_pad}{percentage:3.0f}%|{bar}| ' \
             '{count:!.2j}{unit} / {total:!.2j}{unit} ' \
             '[{elapsed}<{eta}, {rate:!.2j}{unit}/s]'

manager = enlighten.get_manager()
pbar = manager.counter(total=size, desc='Downloading', unit='B', bar_format=bar_format)

bytes_left = size
while bytes_left:
    time.sleep(random.uniform(0.05, 0.15))
    next_chunk = min(chunk_size, bytes_left)
    pbar.update(next_chunk)
    bytes_left -= next_chunk
import enlighten

counter_format = 'Trying to get to sleep: {count:.2h} sheep'

counter = enlighten.Counter(counter_format=counter_format)
counter.count = 0.0
for num in range(10000000):
    counter.update()

For more info, hit up the Counter Format section and the Prefixed documentation 🌈


πŸ’œ WHY IS ENLIGHTEN CALLED ENLIGHTEN? πŸ’œ

A progress bar's whole purpose is to inform the user about an ongoing process. And "Enlighten" literally means "to inform", so… fitting name, no cap. (Also every other name related to progress was already taken 😭)


🌟 IS WINDOWS SUPPORTED? 🌟

Enlighten has supported Windows since version 1.3.0. Periodt.

Windows does not currently support resizing, though. Sad.

Enlighten also works relatively well in Linux-like subsystems for Windows, like Cygwin or Windows Subsystem for Linux. 🫢


πŸŽ€ IS JUPYTER NOTEBOOKS SUPPORTED? πŸŽ€

Experimental support for Jupyter notebooks was added in version 1.10.0. ✨

Jupyter Notebook support is provide by the NotebookManager class. If you're running inside a Jupyter Notebook, get_manager() will return a NotebookManager instance.

There is currently no support for detecting the width of a Jupyter notebook, so output width has been set statically to 100 characters. You can override this by passing the width keyword argument to get_manager().


πŸ“ IS PYCHARM SUPPORTED? πŸ“

PyCharm uses multiple consoles and the behavior differs depending on how the code is called. It's giving chaos.

Enlighten works natively in the PyCharm command terminal.

To use Enlighten with Run or Debug, terminal emulation must be enabled. Navigate to Run -> Edit Configurations -> Templates -> Python and select Emulate terminal in output console.

The PyCharm Python console is currently not supported because sys.stdout does not reference a valid TTY. Rip. πŸ’€


🧚 CAN YOU ADD SUPPORT FOR _______ TERMINAL? 🧚

We are happy to add support for as many terminals as we can. However, not all terminals can be supported. There a few requirements:

  1. The terminal must be detectable programmatically We need to be able to identify the terminal in some reasonable way and differentiate it from other terminals. This could be through environment variables, the platform module, or some other method.
  2. A subset of terminal codes must be supported While these codes may vary among terminals, the capability must be provided and activated by printing a terminal sequence. The required codes are listed below.
    • move / CUP - Cursor Position
    • hide_cursor / DECTCEM - Text Cursor Enable Mode
    • show_cursor / DECTCEM - Text Cursor Enable Mode
    • csr / DECSTBM - Set Top and Bottom Margins
    • clear_eos / ED - Erase in Display
    • clear_eol / EL - Erase in Line
    • feed / CUD - Cursor Down (Or scroll with linefeed)
  3. Terminal dimensions must be detectable The height and width of the terminal must be available to the running process.

😭 WHY DOES RUNTIMEERROR: REENTRANT CALL GET RAISED SOMETIMES DURING A RESIZE? 😭

This is caused when another thread or process is writing to a standard stream (STDOUT, STDERR) at the exact same time the resize signal handler is writing to the stream. Chaos ensues.

Enlighten tries to detect when a program is threaded or running multiple processes and defer resize handling until the next normal write event. However, this condition is evaluated when the scroll area is set β€” typically when the first counter is added. So if no threads or processes are detected at that time, and the value of threaded was not set explicitly, resize events will not be deferred.

In order to guarantee resize handling is deferred, it's best to pass threaded=True when creating a manager instance. Do it bestie, trust.

πŸ™ˆ WHY DOES THE OUTPUT DISAPPEAR AT THE END OF A NOTEBOOK CELL IN VSCODE? πŸ™ˆ

This is caused by a bug in the VSCode Jupyter extension that reverts display updates at the end of a cell. This issue has been confirmed by the maintainers, but a fix has not been released yet. Not me waiting for that patch 😩

As a temporary workaround, manager._primed = False at the end of the cell before calling stop().

Note: this will result in double output in other environments, so it should only be used if the display is cleared first or the code is limited to running in this extension. Be careful out there. 🫑

πŸ‘‘ CLASSES πŸ‘‘

class enlighten.Manager(stream=None, counter_class=Counter, **kwargs)

Parameters

  • stream (file object) -- Output stream. If None, defaults to sys.__stdout__
  • status_bar_class (class) -- Status bar class (Default: StatusBar)
  • counter_class (class) -- Progress bar class (Default: Counter)
  • set_scroll (bool) -- Enable scroll area redefinition (Default: True)
  • companion_stream (file object) -- See companion_stream below. (Default: None)
  • enabled (bool) -- Status (Default: True)
  • no_resize (bool) -- Disable resizing support
  • threaded (bool) -- When True resize handling is deferred until next write (Default: False unless multiple threads or multiple processes are detected)
  • width (int) -- Static output width. If unset, terminal width is determined dynamically
  • kwargs (Dict[str, Any]) -- Any additional keyword arguments will be used as default values when counter() is called.

Manager class for outputting progress bars to streams attached to TTYs πŸ’–

Progress bars are displayed at the bottom of the screen with standard output displayed above. Aesthetic.

companion_stream

A companion stream is a file object that shares a TTY with the primary output stream. The cursor position in the companion stream will be moved in coordination with the primary stream. ✨

If the value is None, the companion stream will be dynamically determined. Unless explicitly specified, a stream which is not attached to a TTY (the case when redirected to a file) will not be used as a companion stream.

counter(position=None, **kwargs)

Parameters

  • position (int) -- Line number counting from the bottom of the screen
  • autorefresh (bool) -- Refresh this counter when other bars are drawn
  • replace (PrintableCounter) -- Replace given counter with new. Position ignored.
  • kwargs (Dict[str, Any]) -- Any additional keyword arguments are passed to Counter

Returns β€” Instance of counter class

Return type β€” Counter

Get a new progress bar instance πŸŽ€

If position is specified, the counter's position will be pinned. A ValueError will be raised if position exceeds the screen height or has already been pinned by another counter. So don't be greedy with positions.

If autorefresh is True, this bar will be redrawn whenever another bar is drawn β€” assuming it had been min_delta seconds since the last update. This is usually unnecessary, ngl.

NOTE: Counters are not automatically drawn when created, because fields may be missing if subcounters are used. To force the counter to draw before updating, call refresh(). ✨

status_bar(*args, **kwargs)

Parameters

  • position (int) -- Line number counting from the bottom of the screen
  • autorefresh (bool) β€” refresh this counter whenever other bars get drawn ✨
  • replace (PrintableCounter) β€” swap the given counter out for a new one. the position gets straight-up ignored, no cap.
  • kwargs (Dict[str, Any]) β€” any extra keyword arguments get passed along to StatusBar

Returns β€” an instance of the status bar class πŸ’–

Return type β€” StatusBar

okay so this is literally just "gimme a new status bar instance" πŸŽ€

if position is specified, the counter's position can change dynamically whenever additional counters are called without a position argument.

if autorefresh is True, this bar gets redrawn every single time another bar is drawn β€” assuming it's been min_delta seconds since the last update. honestly you generally only need this when elapsed is used in status_format.


stop() β€” clean up and reset the terminal 🧹

you call this method when you're done-done with the manager and its counters, like you're never coming back to them.

any progress bars that have leave set to True or that never got closed will stay on the console. everything else gets cleared. poof πŸ’€

the manager and all its counters get disabled.


πŸ¦‹ class enlighten.NotebookManager(stream=None, counter_class=Counter, **kwargs)

Parameters

  • counter_class (class) β€” progress bar class (Default: Counter)
  • status_bar_class (class) β€” status bar class (Default: StatusBar)
  • enabled (bool) β€” status (Default: True)
  • width (int) β€” static output width (Default: 100)
  • kwargs (Dict[str, Any]) β€” any extra keyword arguments get used as default values when counter() is called

this is the manager class for pushing progress bars into Jupyter notebooks πŸ““βœ¨

these keyword arguments get set if you provide them, but then just... ignored πŸ™ˆ

  • stream
  • set_scroll
  • companion_stream
  • no_resize
  • threaded

counter(position=None, **kwargs)

Parameters

  • position (int) β€” line number counting from the bottom of the screen
  • autorefresh (bool) β€” refresh this counter when other bars are drawn
  • replace (PrintableCounter) β€” replace the given counter with a new one. position gets ignored.
  • kwargs (Dict[str, Any]) β€” any extra keyword arguments get passed to Counter

Returns β€” an instance of the counter class πŸ’œ

Return type β€” Counter

grab yourself a brand new progress bar instance, bestie 🌸

if position is specified, that counter's position gets pinned πŸ”’. a ValueError gets raised if position goes past the screen height, or if another counter already pinned that spot.

if autorefresh is True, this bar gets redrawn every time another bar is drawn β€” assuming it's been min_delta seconds since the last update. this is usually unnecessary, fr fr.

NOTE: counters are not automatically drawn when they're created, because fields might be missing if subcounters are used. if you wanna force the counter to draw before updating, call refresh().

status_bar(*args, **kwargs)

Parameters

  • position (int) β€” line number counting from the bottom of the screen
  • autorefresh (bool) β€” refresh this counter when other bars are drawn
  • replace (PrintableCounter) β€” replace the given counter with a new one. position gets ignored.
  • kwargs (Dict[str, Any]) β€” any extra keyword arguments get passed to StatusBar

Returns β€” an instance of the status bar class πŸ’–

Return type β€” StatusBar

new status bar instance, let's goooo ✨

if position is specified, the counter's position can change dynamically if additional counters are called without a position argument.

if autorefresh is True, this bar gets redrawn whenever another bar is drawn β€” assuming it's been min_delta seconds since the last update. you generally only need it when elapsed is used in status_format.


stop() β€” clean up and reset the terminal 🧹

call this when the manager and its counters are no longer needed, periodt.

any progress bars with leave set to True, or that never got closed, will stay on the console. all the others get cleared.

manager and all counters get disabled.


πŸ‘‘ class enlighten.Counter(**kwargs)

Parameters

  • all_fields (bool) β€” populate rate, interval, and eta formatting fields in subcounters
  • bar_format (str) β€” progress bar format, see Format below
  • count (int) β€” initial count (Default: 0)
  • counter_format (str) β€” counter format, see Format below
  • color (str) β€” series color as a string or RGB tuple, see Series Color
  • desc (str) β€” description
  • enabled (bool) β€” status (Default: True)
  • fill (str) β€” fill character used for counter_format (Default: ' ')
  • fields (dict) β€” additional fields used for formatting
  • leave (True) β€” leave progress bar after closing (Default: True)
  • manager (Manager) β€” manager instance. creates an instance if you don't specify one.
  • min_delta (float) β€” minimum time, in seconds, between refreshes (Default: 0.1)
  • offset (int) β€” number of non-printable characters to account for when formatting
  • series (sequence) β€” progression series, see Series below
  • stream (file object) β€” output stream. not used when instantiated through a manager
  • total (int) β€” total count when complete
  • unit (str) β€” unit label

the progress bar and counter class, the moment we've all been waiting for πŸŽ‰

a Counter instance can be made with the Manager.counter() method or β€” when you need a standalone progress bar for a simple app β€” you can just call the Counter class directly. the output stream defaults to sys.__stdout__ unless stream is set.

NOTE: with the default values for bar_format and counter_format, floats cannot be used for total, count, or passed to update(). if you wanna use floats, hand custom formats to bar_format and counter_format. peep Format below.

🌈 Series

the progress bar is constructed from the characters in series. series has to be a sequence (str, list, tuple) containing single characters.

default progress series (series):

' β–β–Žβ–β–Œβ–‹β–Šβ–‰β–ˆ'

the first character is the fill character. when the count is 0, the bar will be made up of only this character. in the example below, characters 5 through 9 are fill characters.

the last character is the full character. when the count equals total, the bar will be made up of only this character. in the example below, characters 0 through 3 are full characters.

the remaining characters are fractional characters, used to more accurately represent the transition between the full and fill characters. in the example below, character 4 is a fractional character.

'45% |β–ˆβ–ˆβ–ˆβ–ˆβ–‹     |'
     '0123456789'

πŸ’… Series Color

the characters specified by series get displayed in the terminal's current foreground color. you can overwrite that with the color argument.

color can be specified as None, a string, or an iterable of three integers, 0 - 255, describing an RGB color.

for backward compatibility, a color can be expressed as an integer 0 - 255, but that's deprecated in favor of named or RGB colors. (we don't do that anymore bestie πŸ™ˆ)

compound colors, like 'white_on_seagreen', 'bold_red', or 'underline_on_peru', are also supported. iconic honestly.

if a terminal isn't capable of 24-bit color and you hand it a color outside its range, the color gets downconverted to a supported one. no drama. πŸ¦‹

valid colors for 8 color terminals:

  • black
  • blue
  • cyan
  • green
  • magenta
  • red
  • white
  • yellow

additional colors for 16 color terminals:

  • bright_black
  • bright_blue
  • bright_cyan
  • bright_green
  • bright_magenta
  • bright_red
  • bright_white
  • bright_yellow

see this chart for the complete list of supported color strings.

NOTE: if you specify an invalid color, an AttributeError gets raised. πŸ’€

⭐ Format

if total is None, or if count goes higher than total, the counter format gets used instead of the progress bar format.

default counter format (counter_format):

'{desc}{desc_pad}{count:d} {unit}{unit_pad}{elapsed}, {rate:.2f}{unit_pad}{unit}/s]{fill}'

# Example output
'Loaded 30042 Files [00:01, 21446.45 Files/s]                                    '

default progress bar format (bar_format), coming right up πŸ‘€:

So that bar_format string is giving main character energy and doing the absolute most, so let's break down every field it can reach for. πŸ’…

'{desc}{desc_pad}{percentage:3.0f}%|{bar}| {count:{len_total}d}/{total:d} [{elapsed}<{eta}, {rate:.2f}{unit_pad}{unit}/s]'

# Example output
'Processing    22%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–Š                   |  23/101 [00:27<01:32, 0.84 Files/s]'

Fields you can use, bestie:

  • count (int) β€” current value of count
  • desc (str) β€” value of desc
  • desc_pad (str) β€” a single space if desc is set, otherwise empty
  • elapsed (str) β€” time elapsed since the instance was created
  • interval (prefixed.Float) β€” average seconds per iteration (it's the inverse of rate, ik)
  • rate (prefixed.Float) β€” average iterations per second since the instance was created
  • total (int) β€” value of total
  • unit (str) β€” value of unit
  • unit_pad (str) β€” a single space if unit is set, otherwise empty

Extra fields that only work in bar_format:

  • bar (str) β€” progress bar drawn with characters from series
  • eta (str) β€” estimated time to completion
  • len_total (int) β€” length of total when it's converted to a string
  • percentage (float) β€” percentage complete

Extra fields that only work in counter_format:

  • fill (str) β€” filled with fill until the line is the width of the terminal. Can be used multiple times. Minimum width is 3.

Extra fields when subcounters are in the mix:

  • count_n (int) β€” current value of count
  • count_0 (int) β€” remaining count after deducting counts for all subcounters
  • count_00 (int) β€” sum of counts from all subcounters
  • interval_0 (prefixed.Float) β€” average seconds per non-subcounter iteration (inverse of rate_0)
  • interval_00 (prefixed.Float) β€” average seconds per iteration for all subcounters (inverse of rate_00)
  • percentage_n (float) β€” percentage complete (bar_format only)
  • percentage_0 (float) β€” remaining percentage after deducting percentages for all subcounters (bar_format only)
  • percentage_00 (float) β€” total of percentages from all subcounters
  • rate_0 (prefixed.Float) β€” average iterations per second excluding subcounters since the instance was created
  • rate_00 (prefixed.Float) β€” average iterations per second of all subcounters since the instance was created
NOTE: that n is literally the order the subcounter was added, starting at 1. So count_1 is the count for the first subcounter added and count_2 is the count for the second subcounter added. iykyk.

Extra fields when add_subcounter() is called with all_fields set to True:

  • eta_n (str) β€” estimated time to completion (bar_format only)
  • interval_n (prefixed.Float) β€” average seconds per iteration (inverse of rate)
  • rate_n (prefixed.Float) β€” average iterations per second since parent was created
NOTE: the count and total fields, including count_0, count_00, and count_n, default to int. But if total or count are set to a float, or a float is provided to update(), these fields become prefixed.Float instead. 🫢 That unlocks extra format specifiers using SI (metric) and IEC (binary) prefixes β€” peep the Prefixed documentation for the deets. Heads up though: this will also require a custom format, and it affects the accuracy of the len_total field. 🫠

User-defined fields: Users can define fields two ways β€” the fields parameter, and by passing keyword arguments to Manager.counter() or Counter.update(). ✨

The fields parameter takes a dictionary of additional user-defined fields. The dictionary values can be updated after initialization, which is how you get dynamic fields. And any fields that share names with built-in fields are just ignored, no drama.

If fields are passed as keyword arguments to Manager.counter() or Counter.update(), they take precedent over the fields parameter. Periodt. πŸ‘‘


Offset πŸ¦‹

When offset is None, the width of the bar portion of the progress bar and the fill size for counter are automatically determined β€” and it even takes into account terminal escape sequences that might be hiding inside the string. Considerate queen.

But under special circumstances, and to permit backward compatibility, offset may be explicitly set to an int value. When you set it explicitly, automatic detection of escape sequences is disabled. So like, know what you're doing. πŸ™ˆ

Instance Attributes 🌸

  • count β€” int β€” current count
  • desc β€” str β€” description
  • elapsed β€” float β€” time since start (since last update if count equals total)
  • enabled β€” bool β€” current status
  • manager β€” Manager β€” Manager Instance
  • position β€” int β€” current position
  • total β€” int β€” total count when complete
  • unit β€” str β€” unit label

add_subcounter(color, count=0, all_fields=None)

Parameters

  • color (str) -- series color as a string or RGB tuple, see Series Color
  • count (int) -- initial count (Default: 0)
  • all_fields (bool) -- populate rate, interval, and eta formatting fields (Default: False unless specified in parent)

Returns β€” Subcounter instance

Return type β€” SubCounter

Add a subcounter for multicolored progress bars. 🌈


clear(flush=True)

Parameters

  • flush (bool) -- flush stream after clearing bar (Default: True)

Clear bar.


close(clear=False)

Do final refresh and remove from manager.

If leave is True (which is the default), the effect is the same as refresh().


property color

Color property.

Preferred to be a string or iterable of three integers for RGB. Single integer supported for backwards compatibility.


property fill

Fill character used in formatting.


format(width=None, elapsed=None)

Parameters

  • width (int) -- width in columns to make progress bar
  • elapsed (float) -- time since started. Automatically determined if None

Returns β€” formatted progress bar or counter

Return type β€” str

Format progress bar or counter.


refresh(flush=True, elapsed=None)

Parameters

  • flush (bool) -- flush stream after writing bar (Default: True)
  • elapsed (float) -- time since started. Automatically determined if None

Redraw bar.


property subcount

Sum of counts from all subcounters.


update(incr=1, force=False, **fields)

Parameters

  • incr (int) -- amount to increment count (Default: 1)
  • force (bool) -- force refresh even if min_delta has not been reached
  • fields (dict) -- fields for for formatting

Increment progress bar and redraw.

Progress bar is only redrawn if min_delta seconds past since the last update.

class enlighten.StatusBar(*args, **kwargs)

Parameters

  • enabled (bool) -- status (Default: True)
  • color (str) -- color as a string or RGB tuple, see Status Color
  • fields (dict) -- additional fields used for formating
  • fill (str) -- fill character used in formatting and justifying text (Default: ' ')
  • justify (str) -- one of Justify.CENTER, Justify.LEFT, Justify.RIGHT
  • leave (True) -- leave status bar after closing (Default: True)
  • min_delta (float) -- minimum time, in seconds, between refreshes (Default: 0.1)
  • status_format (str) -- status bar format, see Format

Status bar class. πŸŽ€

A StatusBar instance should be created with the Manager.status_bar() method.

Status Color πŸ’œ

Color works similarly to color on Counter, except it affects the entire status bar. See Series Color for more information.

Format ⭐

There are two ways to populate the status bar β€” direct and formatted. Direct takes precedence over formatted.

Direct Status

Direct status is used when arguments are passed to Manager.status_bar() or StatusBar.update(). Any arguments are coerced to strings and joined with a space. Like so:

status_bar.update('Hello', 'World!')
# Example output: Hello World!

status_bar.update('Hello World!')
# Example output: Hello World!

count = [1, 2, 3, 4]
status_bar.update(*count)
# Example output: 1 2 3 4

Formatted Status

Formatted status uses the format specified in the status_format parameter to populate the status bar.

'Current Stage: {stage}'

# Example output
'Current Stage: Testing'

Available fields:

  • elapsed (str) -- time elapsed since instance was created
  • fill (str) -- filled with fill until line is width of terminal. May be used multiple times. Minimum width is 3.
NOTE: the status bar is only updated when StatusBar.update() or StatusBar.refresh() is called, so fields like elapsed will need additional calls to appear dynamic. She does not update herself, bestie. 😭

✨ User-defined fields ✨

okay bestie, so you can define fields in TWO ways: the fields parameter, and by passing keyword arguments to Manager.status_bar() or StatusBar.update(). πŸ’…

The fields parameter can be used to pass a dictionary of additional user-defined fields. The dictionary values can be updated after initialization to allow for dynamic fields. Any fields that share names with available fields are ignored. 🚫

If fields are passed as keyword arguments to Manager.status_bar() or StatusBar.update(), they take precedent over the fields parameter. πŸ‘‘


✨ Instance Attributes ✨

  • elapsed β€” float β€” Time since start ⏳
  • enabled β€” bool β€” Current status βœ…
  • manager β€” Manager β€” Manager Instance πŸ‘©β€πŸ’Ό
  • position β€” int β€” Current position πŸ“

🧼 clear(flush=True) 🧼

  • flush (bool) β€” Flush stream after clearing bar (Default: True)

Clear bar.


πŸšͺ close(clear=False) πŸšͺ

Do final refresh and remove from manager.

If leave is True, the default, the effect is the same as refresh(). 🀯


🎨 property color 🎨

Color property.

Preferred to be a string or iterable of three integers for RGB. Single integer supported for backwards compatibility. 🌈


πŸ–ŒοΈ property fill πŸ–ŒοΈ

Fill character used in formatting.


πŸ“ format(width=None, elapsed=None) πŸ“

Parameters:

  • width (int) β€” Width in columns to make progress bar
  • elapsed (float) β€” Time since started. Automatically determined if None

Returns: Formatted status bar.

Return type: str

Format status bar. ✨


βš–οΈ property justify βš–οΈ

Maps to justify method determined by justify parameter.


πŸ”„ refresh(flush=True, elapsed=None) πŸ”„

Parameters:

  • flush (bool) β€” Flush stream after writing bar (Default: True)
  • elapsed (float) β€” Time since started. Automatically determined if None

Redraw bar. πŸ’«


πŸ” update(*objects, **fields) πŸ”

Parameters:

  • objects (list) β€” Values for Direct Status
  • force (bool) β€” Force refresh even if min_delta has not been reached
  • fields (dict) β€” Fields for for Formatted Status

Update status and redraw.

Status bar is only redrawn if min_delta seconds past since the last update. ⏱️


πŸ‘‘ class enlighten.SubCounter(parent, color=None, count=0, all_fields=False) πŸ‘‘

A child counter for multicolored progress bars.

This class tracks a portion of multicolored progress bar and should be initialized through Counter.add_subcounter(). 🌈

✨ Instance Attributes ✨

  • count β€” int β€” Current count
  • parent β€” Counter β€” Parent counter

πŸ” update(incr=1, force=False) πŸ”

Parameters:

  • incr (int) β€” Amount to increment count (Default: 1)
  • force (bool) β€” Force refresh even if min_delta has not been reached

Increment progress bar and redraw.

Both this counter and the parent are incremented.

Progress bar is only redrawn if min_delta seconds past since the last update on the parent. ⏳

πŸ”€ update_from(source, incr=1, force=False) πŸ”€

Parameters:

  • source (SubCounter) β€” SubCounter or Counter to increment from
  • incr (int) β€” Amount to increment count (Default: 1)
  • force (bool) β€” Force refresh even if min_delta has not been reached

Move a value to this counter from another counter.

source must be the parent Counter instance or a SubCounter with the same parent. πŸ‘―


πŸ› οΈ FUNCTIONS πŸ› οΈ

✨ enlighten.get_manager(stream=None, counter_class=Counter, **kwargs) ✨

Parameters:

  • stream (file object) β€” Output stream. If None, defaults to sys.__stdout__
  • counter_class (class) β€” Progress bar class (Default: Counter)
  • kwargs (Dict[str, Any]) β€” Any additional keyword arguments will passed to the manager class.

Returns: Manager instance

Return type: Manager

Convenience function to get a manager instance.

If running inside a notebook, a NotebookManager instance is returned. otherwise a standard Manager instance is returned.

If a a standard Manager instance is used and stream is not attached to a TTY, the Manager instance is disabled. 😭


🌟 CONSTANTS 🌟

🎯 class enlighten.Justify 🎯

Enumerated type for justification options.

  • CENTER β€” Justify center
  • LEFT β€” Justify left
  • RIGHT β€” Justify right

Enlighten Progress Bar is a console progress bar library for Python. 🐍

The main advantage of Enlighten is it allows writing to stdout and stderr without any redirection or additional code. Just print or log as you normally would. πŸ–¨οΈ

Enlighten also includes experimental support for Jupyter Notebooks. πŸ““

The code for this animation can be found in demo.py in examples. 🎬


πŸ‘‘ AUTHOR πŸ‘‘

Avram Lubkin


2023 - 2022, Avram Lubkin


And that's the whole vibe, bestie! This page is from version 1.11.2, dated Feb 26, 2023, and it's literally iconic. Go forth and make your progress bars slay! πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from