Search code examples
pythonprogress-barrich

rich.prompt.Confirm not working in rich.Progress context python


I am working on an app that uses a rich.Progress for rendering progress bars. The problem is rich.prompt.Confirm just flashes instead of showing the message and asking for the confirmation while in the Progress context.

Demo Code

from rich.progress import Progress
from rich.prompt import Confirm
from time import sleep

with Progress() as progress:
    task = progress.add_task('Cooking')
    while not progress.finished:
        if Confirm.ask('Should I continue', default=False):
            progress.update(task, advance=0.6)
            sleep(0.4)

EDIT: I have seen git issues and researched a bit and it seems input(which the rich.Prompt uses) doesn't work on any thing that uses rich.Live(which the rich.Progress uses). So now my question is, How can you structure your code so that you don't put a prompt inside a rich.Progress context manager. Or any possible workarounds to this issue.


Solution

  • So from the Github Issue (That might be the one you talked about), that is now a workaround, thanks to Leonardo Cencetti. The solution is simple. He pause the progress and clear the progress lines. When you are done, he starts the progress again.

    For Future people here is his code:

    from rich.progress import Progress
    class PauseProgress:
        def __init__(self, progress: Progress) -> None:
            self._progress = progress
    
        def _clear_line(self) -> None:
            UP = "\x1b[1A"
            CLEAR = "\x1b[2K"
            for _ in self._progress.tasks:
                print(UP + CLEAR + UP)
    
        def __enter__(self):
            self._progress.stop()
            self._clear_line()
            return self._progress
    
        def __exit__(self, exc_type, exc_value, exc_traceback):
            self._progress.start()
    

    And in you MWC, it is going to be used like:

    from rich.progress import Progress
    from rich.prompt import Confirm
    from time import sleep
    
    with Progress() as progress:
        task = progress.add_task('Cooking')
        while not progress.finished:
            with PauseProgress(progress):
                ok_to_go = Confirm.ask('Should I continue', default=False)
            if not ok_to_go:
                break
            progress.update(task, advance=0.6)
            sleep(1)