简体   繁体   中英

Pause and Unpause TQDM Progress Bar Using Pynput Key Press

I'm creating a small program that uses the TQDM progress bar library, where I would like to press space to "pause" and "unpause" the progress bar. The Progress bar should update every second, and run to 100% when the amount of time entered completes. Please see the attempt I did below, where when running, the progress bar never updates on it's own. Appreciate your feedback.

from tqdm import tqdm
from pynput import keyboard

class TimerTimer:
    def __init__(self, fileLoc) -> None:
        self.timer_list = self.get_timer_list(fileLoc)
        self.timer_length = len(self.timer_list)
        self.kb_listener = None
        self.init_val = 0
        self.wait = False

    def on_press_or_release(self, key):
        if key == keyboard.Key.esc:
            print("Exiting")
            exit()
        if key == keyboard.Key.space:
            self.wait = not self.wait
            printStr = "\nPaused...\n" if self.wait else "\nResumed!"
            print(printStr)
            return False

    def timer_with_progress(self, time_limit, name):
        print("{} for {} seconds:".format(name, time_limit))
        t = tqdm(total=time_limit, desc=name, ncols=100, initial=self.init_val)

        #for i in tqdm(range(time_limit), desc=name, ncols=100, initial=self.init_val):
        for i in range(time_limit):
            # sleep(1)
            # The event listener will be running in this block
            with keyboard.Events() as events:
                # Block at most one second
                event = events.get(1.0)
                if event is None:
                    break
                elif event.key == keyboard.Key.esc:
                    print("Exiting")
                    exit()
                elif event.key == keyboard.Key.space:
                    self.wait = not self.wait
                    printStr = "\nPaused...\n" if self.wait else "\nResumed!"
                    print(printStr)
                else:
                    break

            t.update()
            # t.refresh()
        t.close()

    def run(self):
        for index in self.timer_list:
            timer_cmd_list = ["self.timer_with_progress(5, 'Rest')",
                            "self.timer_with_progress(self.timer_list[index]['durationSeconds'], self.timer_list[index]['timerName'])"]
            for cmd in timer_cmd_list:
                if not self.wait:
                    exec(cmd)
                else:
                    if self.kb_listener is None:
                        self.kb_listener = keyboard.Listener(on_press = self.on_press_or_release) # , on_release = self.on_press_or_release)
                        self.kb_listener.start()
                    self.kb_listener.join() # Waits until the key is pressed again
                    self.wait = not self.wait # Once the button is pressed again, it changes the flag


if __name__=="__main__":
    tt = TimerTimer(filename)
    tt.run()

So after some research, I saw that progressbar2 appears to implement a better interrupt to accomplish what I was aiming to achieve. See below:

import progressbar
from pynput import keyboard
from time import sleep

class TimerTimer:
    def __init__(self, fileLoc) -> None:
        self.timer_list = self.get_timer_list(fileLoc)
        self.timer_length = len(self.timer_list)
        self.wait = False

    def on_press(self, key):
        pass

    def on_release(self, key):
        if key == keyboard.Key.space:
            self.wait = not self.wait
            printStr = "Paused..." if self.wait else "\nResuming..."
            print(printStr)
        elif key == keyboard.Key.esc:
            print("Exiting")
            exit()

    def timer_with_progress(self, time_limit: int, name: str, iter:int=1) -> None:
        """Function that runs the progressbar2 progress bar.

        Keyword arguments:
        time_limit -- (int) The time limit (in seconds) for the progress bar.
        name -- (string) The Name of the progress bar, or the brief description.
        iter -- (int) The iteration time in seconds.  (default 1)
        """
        print("{} for {} seconds:".format(color.BOLD + name +color.END, time_limit))
        bar = progressbar.ProgressBar(max_value=time_limit)
        i = 0
        # Adding keyboard listener
        listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
        listener.start()
        while i <= time_limit:
            sleep(iter)
            if not self.wait:
                bar.update(i)
                i += iter
        bar.finish()

    def run(self):
        for index in self.timer_list:
            self.timer_with_progress(5, 'Rest')
            self.timer_with_progress(self.timer_list[index]['durationSeconds'], self.timer_list[index]['timerName'])


if __name__=="__main__":
    tt = TimerTimer(filename)
    tt.run()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM