4

i have a script which should interact with the users input (pressing the arrow keys), but i cannot get the keys. i tried raw_input and some other functions, but they didnt work. this is my sample code, how it should look like (running bool can be set to False in another function)

running = True
while running:
    #if input == Arrow_UP:
    #    do_Sth
    #elif ...
    display()
    time.sleep(1)

another question is, how can i call the display function only once every second, but react on the input immediately?

vtni
  • 950
  • 3
  • 14
  • 43
  • 1
    Probably duplicated of: http://stackoverflow.com/questions/510357/python-read-a-single-character-from-the-user – Xin Yin Aug 14 '14 at 02:03
  • hi, thanks for your answer, but my second question is still not solved. with getch() the display function is only called when a key is pressed, but i want to call it every second an when a key is pressed another function additionately. – vtni Aug 14 '14 at 11:32
  • @vtni Please post different questions separately – chepner Aug 14 '14 at 12:56

1 Answers1

7

There are different situations:

  • If you use a graphical frontend such as TKinter or PyGame, you can bind an event to the arrow key and wait for this event.

    Example in Tkinter taken from this answer:

    from Tkinter import *
    
    main = Tk()
    
    def leftKey(event):
        print "Left key pressed"
    
    def rightKey(event):
        print "Right key pressed"
    
    frame = Frame(main, width=100, height=100)
    main.bind('<Left>', leftKey)
    main.bind('<Right>', rightKey)
    frame.pack()
    main.mainloop()
    
  • If your application stays in the terminal, consider using curses as described in this answer

    Curses is designed for creating interfaces that run in terminal (under linux).

  • If you use curses, the content of the terminal will be cleared when you enter the application, and restored when you exit it. If you don't want this behavior, you can use a getch() wrapper, as described in this answer. Once you have initialized getch with getch = _Getch(), you can store the next input using key = getch()

As to how to call display() every second, it again depends on the situation, but if you work in a single process in a terminal, the process won't be able to call your display() function while it waits for an input. The solution is to use a different thread for the display() function, as in

import threading;

def display (): 
    threading.Timer(1., display).start ();
    print "display"

display ()

Here display schedules itself one second in the future each time it is called. You can of course put some conditions around this call so that the process stops when some conditions are met, in your case when an input has been given. Refer to this answer for a more thoughout discussion.

Community
  • 1
  • 1
Maxim
  • 7,207
  • 1
  • 30
  • 29
  • thanks a lot! it's an terminal script, so i couldn't use Tkinter, but your second suggestion made it work with getch. I call display() before the loop. – vtni Aug 14 '14 at 11:49
  • I have been trying to use cv2.waitKey on a while loop with a break when user presses but without luck since i want the code to stop on selenium for allowing me to manually do some stuff and let it run after without explicit waits, any idea how to achieve this? – Mr-Programs Jun 17 '20 at 14:13