0

I'm trying to combine the getch and progressbar Python modules on Linux, but I cannot get it to work. I want to use getch to listen for keyboard input to interrupt the progress bar, but when I insert the getch statement, the progress bar refuses to update automatically, only updating when I press a button on the keyboard.

The code I'm currently using is below. I'm using ProgressBar2 and the getch module, but I've tried using tqdm and my own getch method with no avail.

bar = progressbar.ProgressBar()
for i in range(101):
    sleep(0.01)
    bar.update(i)
    ch = getch.getch()

When using my own implementation of getch, I've narrowed down the problem to be with the 'sys.stdin.read(1)' line in the following code.

fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
    tty.setraw(sys.stdin.fileno(), termios.TCSADRAIN)
    ch = sys.stdin.read(1)
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

On Windows, using the msvcrt module, I have no problems whatsoever.

Pieter Helsen
  • 981
  • 1
  • 6
  • 9
  • I'd assume `file.read()` blocks by default. How about [urwid](http://urwid.org/), which has an event loop, keyboard events, a progress bar widget (among others)? – blubberdiblub Jan 22 '17 at 15:53

1 Answers1

0

I've had the same issue on Linux, so I opted for a different solution: capture the SIGINT signal (CTRL+C) to exit gracefully, or immediately after two presses (the regular SIGINT way).

import signal
import time

signal.signal(signal.SIGINT, signal_handler)
sigint_again = False
asked_termination = False

def signal_handler(self, signal, frame):
    """Handles SIGINT signal, blocks it to terminate gracefully"""
    print('You pressed Ctrl+C!:', signal, frame)
    if is_sigint_called_twice():
        print("\nForced terminating script!")
        sys.exit(0)
    asked_termination = True

def is_sigint_called_twice(self):
    """Check if pressing ctrl+c a second time to terminate immediately"""
    if not sigint_again:
        sigint_again = True
        return False
    else:
        return True

while not asked_termination:
    print("do_stuff()")
    time.sleep(1)
Hernn0
  • 89
  • 1
  • 7