This Stack Overflow thread, Detect key press in python? had good examples. In your case because you want to detect only the first "KEY_DOWN" event you want to use on_press_key instead. Using your example it would look something like the following. import keyboard if __name__ == '__main__': keyboard.on_press_key("left arrow", lambda _: print('mkay')) while True: continue Answer from Jackkell100 on reddit.com
🌐
Reddit
reddit.com › r/learnpython › how do you capture arrow key presses?
r/learnpython on Reddit: How do you capture arrow key presses?
June 18, 2021 -

I want to trigger certain functions when pressing certain arrows, it must be captured without being in console and pressing enter each time.

edit: I found now that "left arrow" registers left arrow etc BUT it triggered hundreds of times when pressed

import keyboard
while True:
	if keyboard.is_pressed("left arrow"):
		print("mkay")

Everytime I press, it's very important that it only registeres once, any suggestions how to do that in an efficient manner?

I've got it working pretty good using sleep() efter each press but surely there must be a better way?

Discussions

input - Finding the Values of the Arrow Keys in Python: Why are they triples? - Stack Overflow
I am trying to find the values that my local system assigns to the arrow keys, specifically in Python. I am using the following script to do this: import sys,tty,termios class _Getch: def More on stackoverflow.com
🌐 stackoverflow.com
python - How do I accept input from arrow keys, or accept directional input? - Stack Overflow
This may be an xy problem, but I'm trying to to build a kernel based text editor, similar to vim or nano, and I know how to use the escape chars to clear the screen, then reprint, I can have it acc... More on stackoverflow.com
🌐 stackoverflow.com
input - How to detect when a keyboard arrow key is held down in turtle graphics? - Game Development Stack Exchange
I am very new to Python I started to make a pong game, but can't get it to let me hold down the buttons for the paddle to move. I'm using the builtin turtle module, not Pygame. def paddle_a_up(): ... More on gamedev.stackexchange.com
🌐 gamedev.stackexchange.com
How to press the arrow keys with python keyboard libray? - Stack Overflow
Im trying to make a bot for a game. I need to press the left arrow key but it does not move the camera at all. I think it is using the arrow keys on the numpad and not the 4 arrow keys. How do I fi... More on stackoverflow.com
🌐 stackoverflow.com
🌐
DaniWeb
daniweb.com › programming › software-development › threads › 228595 › getting-an-input-from-arrow-keys
python - Getting an input from arrow keys. [SOLVED] | DaniWeb
If you truly need console input (no GUI), use curses on Unix-like systems; it normalizes arrow keys to curses.KEY_*. This counters the early claim that console is impossible, while staying portable beyond Windows msvcrt.
🌐
Sololearn
sololearn.com › en › Discuss › 1971803 › how-to-get-arrow-keys-input-in-python
How to get arrow keys input in python? | Sololearn: Learn to code for FREE!
Read this, to get an overwiew: https://stackoverflow.com/questions/13207678/whats-the-simplest-way-of-detecting-keyboard-input-in-python-from-the-terminal https://stackoverflow.com/questions/292095/polling-the-keyboard-detect-a-keypress-in-python ... Lothar I meant how to know if the user pressed up arrow key or down arrow key And respond to it accordingly.
🌐
Real Python
realpython.com › lessons › user-input
User Input (Video) – Real Python
K_UP, K_DOWN, K_LEFT, and K_RIGHT correspond to the arrow keys on the keyboard. If the dictionary entry for that key is True, then that key is down, and you move the player .rect in the proper direction.
Published   March 17, 2020
Top answer
1 of 3
51

I think I figured it out.

I learned from here that each arrow key is represented by a unique ANSI escape code. Then I learned that the ANSI escape codes vary by system and application: in my terminal, hitting cat and pressing the up-arrow gives ^[[A, in C it seems to be \033[A, etc. The latter part, the [A, remains the same, but the code for the preceding Escape can be in hex(beginning with an x), octal (beginning with a 0), or decimal(no lead in number).

Then I opened the python console, and plugged in the triples I had previously received, trying to find their character values. As it turned out, chr(27) gave \x1b, chr(91) gave [, and calling chr on 65,66,67,68 returned A,B,C,D respectively. Then it was clear: \x1b was the escape-code!

Then I noted that an arrow key, in ANSI represented as a triple, is of course represented as three characters, so I needed to amend my code so as to read in three characters at a time. Here is the result:

import sys,tty,termios
class _Getch:
    def __call__(self):
            fd = sys.stdin.fileno()
            old_settings = termios.tcgetattr(fd)
            try:
                tty.setraw(sys.stdin.fileno())
                ch = sys.stdin.read(3)
            finally:
                termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
            return ch

def get():
        inkey = _Getch()
        while(1):
                k=inkey()
                if k!='':break
        if k=='\x1b[A':
                print "up"
        elif k=='\x1b[B':
                print "down"
        elif k=='\x1b[C':
                print "right"
        elif k=='\x1b[D':
                print "left"
        else:
                print "not an arrow key!"

def main():
        for i in range(0,20):
                get()

if __name__=='__main__':
        main()
2 of 3
8

I am using Mac and I used the following code and it worked well: I got the values for my arrow keys as 0,1,2,3 (Up, Down, Left, Right): Always good to remember code 27 for ESC key too. Best regards!

while True:
    key = cv2.waitKey(1) & 0xFF

    # if the 'ESC' key is pressed, Quit
    if key == 27:
        quit()
    if key == 0:
        print "up"
    elif key == 1:
        print "down"
    elif key == 2:
        print "left"
    elif key == 3:
        print "right"
    # 255 is what the console returns when there is no key press...
    elif key != 255:
        print(key)
🌐
Quora
quora.com › In-Python-how-do-I-refer-to-keyboard-events-that-involve-the-arrow-keys-up-left-right-down
In Python, how do I refer to keyboard events that involve the arrow keys (up, left, right, down)? - Quora
In short there’s no simple answer ... and libraries. ... In Python GUI and event frameworks the arrow keys are exposed as specific key names or keycodes....
Find elsewhere
Top answer
1 of 5
10

curses is exactly what you want. In fact I believe vim implements its interface with curses.

Try to put the following code into a file called test_curses.py:

import curses

screen = curses.initscr()
screen.addstr("Hello World!!!")
screen.refresh()
screen.getch()
curses.endwin()

Now open a terminal (not IDLE! a real terminal!) and run it via:

python test_curses.py

You should see that the terminal was cleared and an Hello World!!! writing appeared. Press any key and the program will stop, restoring the old terminal contents.

Note that the curses library isn't as easy and "user-friendly" as you may be accustomed to. I suggest reading the tutorial (unfortunately for the C language, but the python interface is mostly the same)

2 of 5
5

I know that I'm late to the party, but I really liked click package mentioned by @elbaschid. I don't know why he wasn't upvoted - maybe because his example doesn't show how to handle specifically cursor keys.

Here is my $0.02 on that:

#!/usr/bin/python

import click

printable = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

while True:
    click.echo('Continue? [yn] ', nl=False)
    c = click.getchar()
    click.echo()
    if c == 'y':
        click.echo('We will go on')
    elif c == 'n':
        click.echo('Abort!')
        break
    elif c == '\x1b[D':
        click.echo('Left arrow <-')
    elif c == '\x1b[C':
        click.echo('Right arrow ->')
    else:
        click.echo('Invalid input :(')
        click.echo('You pressed: "' + ''.join([ '\\'+hex(ord(i))[1:] if i not in printable else i for i in c ]) +'"' )

This handles cursor keys and as a bonus prints py-string representation of any keyboard shortcut it doesn't yet recognize. For example Ctrl-s is "\x13". You can later use it inside another

elif c == ??

I've tried to add edit to @elbaschid answer but it was rejected ¯\_(ツ)_/¯. Please give him credit if you also like my answer

Awesome library for quick command-line prototyping.

🌐
Codehaven
codehaven.co.uk › python › using-arrow-keys-with-inputs-python
How to use Arrow Keys with inputs - Python
Using arrow keys with python can be tricky so the code below should help: – import curses · # get the curses screen window screen = curses.initscr() # turn off input echoing curses.noecho() # respond to keys immediately (don't wait for enter) curses.cbreak() # map arrow keys to special values screen.keypad(True) try: while True: char = screen.getch() if char == ord('q'): break elif char == curses.KEY_RIGHT: # print doesn't work with curses, use addstr instead screen.addstr(0, 0, 'right') elif char == curses.KEY_LEFT: screen.addstr(0, 0, 'left ') elif char == curses.KEY_UP: screen.addstr(0, 0, 'up ') elif char == curses.KEY_DOWN: screen.addstr(0, 0, 'down ') finally: # shut down cleanly curses.nocbreak(); screen.keypad(0); curses.echo() curses.endwin()
Top answer
1 of 2
1

System sends to programs information about pressed key ("events") only when key changes state from not-pressed to pressed or from pressed to not-pressed (released). It doesn't send events when you hold down key.

You have to use onkeypressed() to set arrow_up_pressed = True and onkeyreleased() to reset arrow_up_pressed = False and ontimer() to run repeatedly code which checks if arrow_up_pressed is True and move object up. The same you should do with arrow_down_pressed, etc.

Or you can use variable speed instead of arrow_up_pressed and arrow_down_pressed so you can assing +15 or -15 to the same variable (or 0 when keys are released). And again you need ontimer to run repeatedly code which add speed to position.

In example I use second method.


Minimal working code

import turtle

def paddle_a_up():
    global a_speed_y

    a_speed_y = +15

def paddle_a_down():
    global a_speed_y
    
    a_speed_y = -15

def paddle_a_left():
    global a_speed_x

    a_speed_x = -15

def paddle_a_right():
    global a_speed_x
    
    a_speed_x = +15

def paddle_a_stop_y():
    global a_speed_y

    a_speed_y = 0

def paddle_a_stop_x():
    global a_speed_x

    a_speed_x = 0

def update_frame():
    x, y = paddle_a.position()
    
    y += a_speed_y
    x += a_speed_x

    paddle_a.goto(x, y)

    # here update position for other objects - ie. move ball

    # run again after 50ms
    wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000/50 = 20)

# --- main ---

# default values at start
a_speed_x = 0
a_speed_y = 0

wn = turtle.Screen()
paddle_a = turtle.Turtle()

# run first time after 50ms
wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000ms / 50ms = 20)

# binds
wn.onkeypress(paddle_a_up, "Up")
wn.onkeypress(paddle_a_down, "Down")
wn.onkeypress(paddle_a_left, "Left")
wn.onkeypress(paddle_a_right, "Right")

wn.onkeyrelease(paddle_a_stop_y, "Up")
wn.onkeyrelease(paddle_a_stop_y, "Down")
wn.onkeyrelease(paddle_a_stop_x, "Left")
wn.onkeyrelease(paddle_a_stop_x, "Right")

wn.listen()
wn.mainloop()

BTW: The same way you would have to do this in PyGame or Pyglet.


You get better result if you add/substract value to speed instead of assigning - because when you press left and right at the same time then it will stop move (because speed +15 and -15 will gives 0), and when you release only one - ie. left - then it will again move right. In previous version when you release one but you still keep pressed other then it doesn't move again.

import turtle

def paddle_a_up_pressed():
    global a_speed_y

    a_speed_y += 15

def paddle_a_down_pressed():
    global a_speed_y
    
    a_speed_y -= 15

def paddle_a_left_pressed():
    global a_speed_x

    a_speed_x -= 15

def paddle_a_right_pressed():
    global a_speed_x
    
    a_speed_x += 15

def paddle_a_up_released():
    global a_speed_y

    a_speed_y -= 15

def paddle_a_down_released():
    global a_speed_y

    a_speed_y += 15

def paddle_a_left_released():
    global a_speed_x

    a_speed_x += 15

def paddle_a_right_released():
    global a_speed_x

    a_speed_x -= 15


def update_frame():
    x, y = paddle_a.position()
    
    x += a_speed_x
    y += a_speed_y

    paddle_a.goto(x, y)

    # run again after 50ms
    wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000/50 = 20)

# --- main ---

# default values at start
a_speed_x = 0
a_speed_y = 0

wn = turtle.Screen()
paddle_a = turtle.Turtle()

# run first time after 50ms
wn.ontimer(update_frame, 50)  # 50ms means ~20 FPS (Frames Per Second) (1000/50 = 20)

# binds
wn.onkeypress(paddle_a_up_pressed, "Up")
wn.onkeypress(paddle_a_down_pressed, "Down")
wn.onkeypress(paddle_a_left_pressed, "Left")
wn.onkeypress(paddle_a_right_pressed, "Right")

wn.onkeyrelease(paddle_a_up_released, "Up")
wn.onkeyrelease(paddle_a_down_released, "Down")
wn.onkeyrelease(paddle_a_left_released, "Left")
wn.onkeyrelease(paddle_a_right_released, "Right")

wn.listen()
wn.mainloop()
2 of 2
0

The tail end of the existing answer is good, suggesting an update loop with decoupled event handlers.

But I'd go a step further. Instead of applying movement in the key handlers as done in that answer, I'd only record which keys are pressed in the handler. Then handle movement fully in the update loop based on which keys are pressed for that frame.

You can also take advantage of dicts, sets and loops to avoid repetition.

from turtle import Screen, Turtle


def update_frame():
    x, y = paddle_a.position()

    for key in keys:
        dx, dy = movements[key]
        x += dx
        y += dy

    paddle_a.goto(x, y)
    wn.ontimer(update_frame, 1000 // 30)


def bind(key):
    wn.onkeypress(lambda: keys.add(key), key)
    wn.onkeyrelease(lambda: keys.remove(key), key)


step_size = 8
movements = {
    "Up": (0, step_size), 
    "Down": (0, -step_size), 
    "Left": (-step_size, 0), 
    "Right": (step_size, 0), 
}
keys = set()
paddle_a = Turtle()
wn = Screen()

for key in movements.keys():
    bind(key)

wn.listen()
update_frame()
wn.exitonclick()

See also:

  • How to bind several key presses together in turtle graphics?
  • How do I add collision between two player controlled turtles
🌐
Reddit
reddit.com › r/learnpython › python input function arrow key input
r/learnpython on Reddit: Python input function arrow key input
November 6, 2019 -

I have a python script that uses the input function to get some user input. When I run the script and use the arrow keys, it creates symbols like ^[[D, ^[[C, etc. Instead, I want the cursor to move when I use the arrow keys. How do I do it?

🌐
GeeksforGeeks
geeksforgeeks.org › python › python-arcade-handling-keyboard-input
Python Arcade - Handling Keyboard Input - GeeksforGeeks
September 23, 2021 - on_key_press(): This function will be called whenever a keyboard key is pressed. Inside this function, we will check if the key pressed is the up arrow key then we will print "upper arrow key is pressed".
🌐
Raspberry Pi
raspberrypi.org › forums › viewtopic.php
python arrow control - Raspberry Pi Forums
August 6, 2017 - The other block (straight) will never be executed, because a previous block always will be. Given that, it looks like it should work. The KEY_UP block does the job of straight anyway. Press the turn keys once to start a maneuver, and press the UP/DOWN keys once to end it.
Top answer
1 of 1
8

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.

🌐
GeeksforGeeks
geeksforgeeks.org › python-drawing-design-using-arrow-keys-in-pygame
Python – Drawing design using arrow keys in PyGame | GeeksforGeeks
April 22, 2020 - It includes computer graphics and sound libraries designed to be used with the Python programming language. Now, it’s up to the imagination or necessity of developer, what type of game he/she wants to develop using this toolkit. In this article we will see how we can make design in PyGame with help of keys such that design i.e marker moves horizontally when pressing the right arrow key or left arrow key on the keyboard and it moves vertically when pressing up arrow key or down arrow key.
🌐
GitHub
github.com › magmax › python-readchar › issues › 20
arrow keys not being sent to readkey() · Issue #20 · magmax/python-readchar
November 27, 2016 - UP ARROW") if keypress == readchar.key.BACKSPACE: self.input_buff = self.input_buff[:-1] print("\033[0A%s " % self.input_buff) continue if keypress != readchar.key.CR and len(keypress) < 2: self.input_buff = "%s%s" % (self.input_buff, keypress) if self.input_buff[0:1] == '/': # / commands receive special magenta coloring print("%s\033[0A\033[35m%s\033[0m" % (self.cursor, self.input_buff)) else: print("%s\033[0A%s" % (self.cursor, self.input_buff)) continue consoleinput = "%s" % self.input_buff self.input_buff = ""
Author   suresttexas00