In the middle of some process I have a pause with countdown (for loop with time.sleep(1) inside). I'd like to be able to break it with keyboard to be able to continue earlier than countdown got finished. Is it possible with python3 (cross-platform without Linux root access)? Can I get some information about key pressed in this case ?
CodePudding user response:
Related to this question: Use getch in while (1) python
Solution: use kbhit()
and getch()
: https://docs.python.org/3.10/library/msvcrt.html#console-i-o
Working example:
import msvcrt
from time import sleep
def a():
for n in range(10):
if msvcrt.kbhit():
return msvcrt.getch()
sleep(1)
Note that it has a reaction delay of up to 1 second
CodePudding user response:
Here is my "cross-platform" very simplified solution.
def my_sleep(wait_sec):
current_platform = platform.system()
if current_platform == "Windows":
import msvcrt
elif current_platform == "Linux":
import termios
from select import select
# save the terminal settings
fd = sys.stdin.fileno()
new_term = termios.tcgetattr(fd)
old_term = termios.tcgetattr(fd)
# switch to normal terminal
def set_normal_term():
termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)
# switch to unbuffered terminal
def set_curses_term():
termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)
def kbhit():
dr, dw, de = select([sys.stdin], [], [], 0)
return dr != []
set_curses_term()
# new terminal setting unbuffered
new_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)
set_curses_term()
for sec_left in range(wait_sec):
if current_platform == 'Windows':
if msvcrt.kbhit():
# print(f':: {msvcrt.getch()}')
break
elif current_platform == 'Linux':
if kbhit():
ch = sys.stdin.read(1)
# print(f':: {ch}')
break
print(sec_left)
time.sleep(1)
if current_platform == "Linux":
set_normal_term()