marimo icon indicating copy to clipboard operation
marimo copied to clipboard

`rich.progress` support

Open williambdean opened this issue 1 year ago • 5 comments

The rich.progress module provides progress bars for stdout. However, the result is not displayed until after the progress bar is complete which defeats the point.

I've tried many of the examples in the documentation here and I have not had luck with all I have tried.

I tried on the current main branch of the marimo (0.9.17) and version of rich 13.7.0

Example code

import marimo

__generated_with = "0.9.17"
app = marimo.App(width="full")


@app.cell
def __():
    import time
    from rich.progress import track, Progress, BarColumn, TextColumn
    from rich.table import Column

    for i in track(range(10), description="Processing..."):
        time.sleep(1)  # Simulate work being done
    return BarColumn, Column, Progress, TextColumn, i, time, track


@app.cell
def __(Progress, time):
    total = 10

    with Progress() as progress:
        task1 = progress.add_task("[red]Downloading...", total=total)
        task2 = progress.add_task("[green]Processing...", total=total)
        task3 = progress.add_task("[cyan]Cooking...", total=total)

        while not progress.finished:
            progress.update(task1, advance=0.5)
            progress.update(task2, advance=0.3)
            progress.update(task3, advance=0.9)
            time.sleep(0.02)
    return progress, task1, task2, task3, total


@app.cell
def __(Progress, progress):
    def do_work(task):
        print(task)

    with Progress(transient=True) as progress2:
        task = progress.add_task("Working", total=100)
        do_work(task)
    return do_work, progress2, task


@app.cell
def __(BarColumn, Column, Progress, TextColumn, progress, time):
    text_column = TextColumn(
        "{task.description}",
        table_column=Column(ratio=1),
    )
    bar_column = BarColumn(bar_width=None, table_column=Column(ratio=2))

    with Progress(text_column, bar_column, expand=True):
        for n in progress.track(range(10)):
            progress.print(n)
            time.sleep(0.1)
    return bar_column, n, text_column


if __name__ == "__main__":
    app.run()

williambdean avatar Nov 12 '24 01:11 williambdean

We might need to add marimo support to rich directly https://github.com/Textualize/rich/blob/43d3b04725ab9731727fb1126e35980c62f32377/rich/console.py#L517-L534

Would you be open to create an issue on rich?

mscolnick avatar Nov 12 '24 02:11 mscolnick

We might need to add marimo support to rich directly https://github.com/Textualize/rich/blob/43d3b04725ab9731727fb1126e35980c62f32377/rich/console.py#L517-L534

Would you be open to create an issue on rich?

Sure. What is the logic to detect for marimo?

williambdean avatar Nov 12 '24 09:11 williambdean

@wd60622, there is this logic from another open-source project:

https://github.com/run-house/runhouse/blob/2f80fe25879d7df0f3b8432cf62b3c0519d7ea36/runhouse/resources/module.py#L1073-L1080

        # Check if running in a marimo notebook
        try:
            import marimo
            return marimo.running_in_notebook()
        except (ImportError, ModuleNotFoundError):
            # marimo not installed
            return False

mscolnick avatar Nov 12 '24 16:11 mscolnick

In the short term, I've been using this to monkey-patch Rich and make it think it is outputting to a terminal:

import rich.console


_orig_console = rich.console.Console


class Console(_orig_console):
    def __init__(self, *args, **kwargs):
        kwargs["force_terminal"] = True
        super().__init__(*args, **kwargs)


rich.console.Console = Console

This allows the progress bar to update in real time.

smutch avatar Nov 21 '24 02:11 smutch

Thanks for that lead. That doesn't work for my use-case unfortunately.

I'm doing something like this

PyMC x Marimo
import marimo

__generated_with = "0.12.8"
app = marimo.App()


@app.cell
def _():
    import pymc as pm
    import numpy as np

    seed = sum(map(ord, "Marimo x PyMC"))
    rng = np.random.default_rng(10)

    return np, pm, rng, seed


@app.cell
def _():
    nuts_sampler = "pymc"
    return (nuts_sampler,)


@app.cell
def _(model, nuts_sampler, pm):
    with model:
        idata = pm.sample(10_000, nuts_sampler=nuts_sampler)

    idata
    return (idata,)


@app.cell
def _(pm, rng):
    coords = {"date": [1, 2, 3]}
    model = pm.Model(coords=coords)

    data = rng.normal(loc=0, scale=3, size=1000)

    with model:
        mu = pm.Normal("mu")
        sigma = pm.HalfNormal("sigma")
        nu = pm.HalfNormal("nu")
        pm.StudentT("obs", nu=nu, mu=mu, sigma=sigma, observed=data)
    return coords, data, model, mu, nu, sigma


@app.cell
def _(model):
    model
    return


@app.cell
def _():
    import rich.console

    _orig_console = rich.console.Console

    class Console(_orig_console):
        def __init__(self, *args, **kwargs):
            kwargs["force_terminal"] = True
            super().__init__(*args, **kwargs)

    rich.console.Console = Console
    return Console, rich


if __name__ == "__main__":
    app.run()

williambdean avatar Apr 11 '25 18:04 williambdean

I think this is maybe due to the ordering of things. It should work if you place the monkey patching code in the same cell as where you import pymc, and make sure it comes before the pymc import.

Having said that, I just tried it with pymc and instead of clearing and redrawing the parallel progressbars, it just prints a new copy of them for every iteration. :(

smutch avatar May 09 '25 10:05 smutch

it would be great to push support directly into rich.console. would anyone be interested in either filing an issue or making the contribution to that repo?

mscolnick avatar Jun 02 '25 15:06 mscolnick

That hack doesnt work. However, I will raise an issue on the rich repo

williambdean avatar Jun 02 '25 19:06 williambdean

The answer over there is that it should be implemented in marimo

williambdean avatar Jun 02 '25 23:06 williambdean

Given all their shims and customization for rendering in Jupyter, I would imagine we would need the same for marimo

mscolnick avatar Jun 03 '25 01:06 mscolnick