3

I recently got to know about the python module signal. With that, we can capture a SIGINT and do what we want after capturing it. I used it as below. In that case I am just using SIGINT to print that program is going to be stopped and stop the program.

import signal  
import os
import time

def signalHandler(signalnumb, frame):  
    print("Signal Number:", signalnumb, " Frame: ", frame)
    print('Exiting the program...')
    os._exit(0)
 
signal.signal(signal.SIGINT, signalHandler)
 
c=0
# Loop infinite times using the while(1) which is always true
while 1:
    print(c)
    #sleep for 1 seconds using the sleep() function in time 
    time.sleep(1)
    c=c+1

Now I want to give any signal from keyboard(for example pressing 'q') and as soon as signal was recieved, the python program should be stopped. Has anyone got some experience on how to do that? Any other method rather than using signal module (for example using multithreading) is accepted.

Edit1- Later I tried to use pynput module as suggested in one of a similar kind of question. For sure I have done a mistake. It doesn't work as I expected. It means with a key press, I couldn't stop the for loop from running.

from pynput import keyboard
import time

def on_press(key):
    for i in range(100):
        print(i)
        time.sleep(1)
        if key == keyboard.Key.esc:
            return False  # stop listener
        try:
            k = key.char  # single-char keys
        except:
            k = key.name  # other keys
        if k in ['1', '2', 'left', 'right']:  # keys of interest
            # self.keys.append(k)  # store it in global-like variable
            print('Key pressed: ' + k)
            return False  # stop listener; remove this if want more keys

listener = keyboard.Listener(on_press=on_press)
listener.start()  # start to listen on a separate thread
listener.join()  # remove if main thread is polling self.keyspython

Can someone point out how to do it using pynput in correct way?

tad
  • 117
  • 7
  • 2
    Does this answer your question? [Key Listeners in python?](https://stackoverflow.com/questions/11918999/key-listeners-in-python) – C_Z_ Jun 28 '22 at 21:41
  • I tried using pynput package. And I tried to stop a for loop from running using that. I couldn't do it though. – tad Jun 28 '22 at 22:59
  • Can you include the code in you wrote in an attempt to use the pynput package? It should be possible with multithreading – C_Z_ Jun 29 '22 at 00:41
  • @C_Z_ I edited the question by adding the experiment I did with pynput. – tad Jun 29 '22 at 04:24
  • 1
    Thanks, could you give a little more information about your use case? What sort of program are you building, and why do you need to exit out when the key 'k' is pressed? – C_Z_ Jun 29 '22 at 14:57
  • 1
    @C_Z_ thank because you really tried to help. I just went through threads and figured the way of doing it. Thanks again. – tad Jun 29 '22 at 16:14
  • 1
    Glad it all worked out! You should update this question with the answer you found, in case someone else has the same question – C_Z_ Jun 29 '22 at 18:08

2 Answers2

1

This was my original implementation:

a = input('Press a key to exit')
if a:
    exit(0)

However, it seems that you need a piece of code that will allow for any key to be clicked and immediately exit out of the program, without hitting enter afterwards. This may be a better way to do that:

import readchar
print("Press Any Key To Exit")
k = readchar.readchar()

Hope this helps!

Jonathan Joshua
  • 222
  • 1
  • 10
  • OP already has a main loop going, they need something to listen for the key outside their main program control. So... thanks for your contribution, but this is not really an answer. – joanis Jun 28 '22 at 21:44
  • Yeah I now realize that, upon seeing that, I will update my answer to better help OP, thank you! – Jonathan Joshua Jun 28 '22 at 21:51
  • If `readchar()` is blocking, the updated code has the same problem since OP seems to want their program to do something else at the same time. – joanis Jun 28 '22 at 21:58
  • @Jonathan Joshua, I tried to stop a running for loop with readchar. But it does not stop until the for loop is finished. – tad Jun 28 '22 at 22:56
  • simply what I want is this. the python program should be running without any interruption, but when I press a key, the signal should be recieved by the program and program should be stopped or program should react as we defined in the code. – tad Jun 28 '22 at 23:05
1

After carefully understanding about the threads and pynput module, I managed to stop a for loop (or any program which runs as a separate thread) using a key press callback.

from pynput import keyboard
import os
import threading
import time

loop_running = False

def on_press(key):
    print(dir(key))
    global loop_running
    #if key == keyboard.Key.delete and not loop_running:
    if ('char' in dir(key)) and (key.char == 's') and (not loop_running):
        t=threading.Thread(target=start_loop)
        t.start()
        
    #elif key==keyboard.Key.tab:   #if this is used, the attributes related to 'key' will be changed. you can see them since I have used a print(dir(key))
    elif key.char == 'q':
        loop_running=False
        

def start_loop():
    global loop_running
    loop_running = True
    for i in range(100):
        if not loop_running:
            os._exit(0)                          
            
        print(i)
        time.sleep(1)
        
with keyboard.Listener(on_press=on_press) as listner:
    listner.join()
tad
  • 117
  • 7