track-progress

Track progress

!!! abstract “”

How to choose your preferred progress bar backend and customise progress bars.

scinexus defaults to using the tqdm for progress bars. These behave well across terminal and notebook environments. We also support using rich for its progress bars. A single API for different progress backends.

Choosing the progress bar backend

Use set_progress_backend to switch between backends. The default is tqdm.

```python { notest } import scinexus

scinexus.set_progress_backend(“rich”) # switch to rich scinexus.set_progress_backend(“tqdm”) # switch back to tqdm scinexus.set_progress_backend(None) # reset to default (tqdm)


## Getting a progress bar

Use `get_progress` to obtain a `Progress` instance. Passing `show_progress=True` returns the current default backend.

```python { notest }
import scinexus

pbar = scinexus.get_progress(show_progress=True)

for item in pbar(range(100), msg="Processing"):
    pass  # your work here

You can pass keyword arguments to configure the default backend:

```python { notest } import scinexus

pbar = scinexus.get_progress(show_progress=True, colour=“blue”, leave=True)


You can also pass a `Progress` instance directly:

```python { notest }
from scinexus.progress import RichProgress

pbar = scinexus.get_progress(show_progress=RichProgress())

!!! note

If you call `get_progress(show_progress=False)`, it returns `NoProgress`, which silently passes through the iterable.

Nesting progress bars

=== “Using tqdm (default)”

Create nested progress bars using `child()`. Each bar can have its own description via the `msg` keyword. Create the child once before the loop — it automatically resets to zero on each subsequent call.

```python { notest }
import scinexus

pbar = scinexus.get_progress(show_progress=True)
child = pbar.child()

for batch in pbar(range(3), msg="Outer loop"):
    for item in child(range(10), msg=f"Inner batch {batch}"):
        pass  # your work here
```

=== “Using rich

The same nesting pattern works with the `rich` backend:

```python { notest }
import scinexus

scinexus.set_progress_backend("rich")
pbar = scinexus.get_progress(show_progress=True)
child = pbar.child()

for batch in pbar(range(3), msg="Outer loop"):
    for item in child(range(10), msg=f"Inner batch {batch}"):
        pass  # your work here
```

`rich` children share the same `rich.progress.Progress` display instance, so all bars render together in a single live display.

The outer bar tracks the top-level iteration. Each call to child() creates a new Progress at the next cursor position, so inner bars appear below the outer one. The child bar is reused across iterations — on the second and subsequent calls, the bar resets to zero instead of creating a new one.

Push-based sub-contexts

When you need to report fractional progress rather than iterating, use context():

```python { notest } import scinexus

pbar = scinexus.get_progress(show_progress=True)

child = pbar.child() for batch in pbar(range(3), msg=“Processing”): with child.context(msg=f”Batch {batch}“) as ctx: for i in range(100): ctx.update(progress=i / 100, msg=f”Step {i}“)


The context maps progress values from `[0.0, 1.0]` to the configured `[start, end]` range and is cleaned up automatically when the `with` block exits.

## Cleaning up

Both `Progress` and `ProgressContext` support the context manager protocol. Using a progress bar as a context manager ensures that `close()` is called automatically, which finalises the display and moves the cursor past the bars. Without cleanup, leftover bars can leave the terminal cursor in the wrong position.

=== "Using `tqdm` (default)"

    ```python
    import scinexus

    with scinexus.get_progress(show_progress=True) as pbar:  # (1)!
        child = pbar.child()
        for batch in pbar(range(3), msg="Outer"):
            for item in child(range(10), msg=f"Batch {batch}"):
                pass
    ```

    1. `close()` is called automatically and the cursor position is restored.

=== "Using `rich`"

    ```python
    import scinexus

    scinexus.set_progress_backend("rich")
    with scinexus.get_progress(show_progress=True) as pbar:  # (1)!
        child = pbar.child()
        for batch in pbar(range(3), msg="Outer"):
            for item in child(range(10), msg=f"Batch {batch}"):
                pass
    ```

    1. `close()` is called automatically and the cursor position is restored.

???- tip "No context manager? No problem!"

    ```python
    import scinexus

    pbar = scinexus.get_progress(show_progress=True)
    child = pbar.child()
    for batch in pbar(range(3), msg="Outer"):
        for item in child(range(10), msg=f"Batch {batch}"):
            pass
    pbar.close()  # (1)!
    ```

    1. Call `close()` explicitly when you are done

    !!! note

        Calling `close()` on a `Progress` instance also closes all of its children. For standalone `ProgressContext` objects (from `context()`), use the `with` statement as shown in the [push-based sub-contexts](#push-based-sub-contexts) section.

## Customising appearance

### Persisting bars after completion

By default, `tqdm` keeps the outermost bar visible after completion but clears nested bars. `rich` removes all bars. Use `leave` to control this:

```python { notest }
from scinexus.progress import TqdmProgress, RichProgress

# Keep all tqdm bars visible after completion
pbar = TqdmProgress(leave=True)

# Keep all rich bars visible after completion
pbar = RichProgress(leave=True)

You can also set leave independently on child bars:

```python { notest } from scinexus.progress import TqdmProgress

pbar = TqdmProgress(leave=True) child = pbar.child(leave=False) # child bars disappear, outer persists

for batch in pbar(range(3), msg=“Outer”): for item in child(range(10), msg=f”Batch {batch}“): pass


### Setting bar colour

Both backends support a `colour` parameter. For `tqdm`, this sets the bar colour directly. For `rich`, it styles the bar column when the display is auto-created.

```python { notest }
from scinexus.progress import TqdmProgress, RichProgress

pbar = TqdmProgress(colour="green")
pbar = RichProgress(colour="cyan")

Colour is inherited by child bars.