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
The end goal here is in that I'm trying to write a program which needs to correctly recognize arrow-keys and perform a function depending on which arrow-key was pressed. ... I would suggest ANSI escape code even though that lacks a clear section on escape codes that are sent by the keyboard; their ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
How to implement using arrow keys for the game? Maybe a command recall?
so is there a difference between ... 101-key keyboard rather than using the numlock pad arrows? Somewhat related.... how to implement a command recall? In the case I am ยท not using the arrow keys for movement, it would be nice to be able to use the up arrow key for command recall so I wouldn't need to retype the move command words each time... ... The issue with using arrow keys with a regular python script is ... More on teamtreehouse.com
๐ŸŒ teamtreehouse.com
2
August 15, 2017
python get arrow keys from command line - Stack Overflow
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 c... More on stackoverflow.com
๐ŸŒ stackoverflow.com
click - Python, check if arrow key pressed - Stack Overflow
Note that with 'keyboard.Key' you can detect the key that you want. You can even reproduce the case of holding two keys at the same time and detecting a combination! ... This is the code I made, but it's only for a Pygame project with a window If you need the arrows in pygame I recommend this code: More on stackoverflow.com
๐ŸŒ stackoverflow.com
Top answer
1 of 3
4

The keyboard module has simple solutions for instances like these, they use event-triggered activation rather than polling as is used in your attempt.

example code:

import keyboard

def handleLeftKey(e):
    if keyboard.is_pressed("4"):
        print("left arrow was pressed w/ key 4")
        # work your magic

keyboard.on_press_key("left", handleLeftKey)
# self-explanitory: when the left key is pressed down then do something

keyboard.on_release_key("left", handleLeftKey02)
# also self-explanitory: when the left key is released then do something

# don't use both ...on_release & ...on_press or it will be
# triggered twice per key-use (1 up, 1 down)

Replace the code below and change it to suit your needs.

if __name__ == "__main__":
    while True:
        code = []
        try:
            for key in keys:
                if keyboard.is_pressed(key):
                    print(keyboard.key_to_scan_codes(key))
                    print(f"{key} pressed")
                    code.append(1)
                else:
                    code.append(0)

Another, more dynamic approach would look like:

import keyboard

keys = [
    "down",
    "up",
    "left",
    "right",
    "w",
    "s",
    "a",
    "d",
    "1",
    "2",
    "3",
    "4",
    "q",
    "e",
    "f"
]

def kbdCallback(e):
    found = False
    for key in keys:
        if key == keyboard.normalize_name(e.name):
            print(f"{key} was pressed")
            found = True
            # work your magic

    if found == True:
        if e.name == "left":
            if keyboard.is_pressed("4"):
                print("4 & left arrow were pressed together!")
                # work your magic

keyboard.on_press(kbdCallback)
# same as keyboard.on_press_key, but it does this for EVERY key

Another issue I noticed was that you were using "left arrow" when really it was recognized as "left" (at least on my system, it may be different on yours, but I assume you want it to work on all systems so it'd be safer using "left" instead)

The last method you could use is very statically typed and has no dynamic capabilities, but would work in the case of "4+left" or "left+4"

import keyboard

def left4trigger:
    print("the keys were pressed")

keyboard.add_hotkey("4+left", left4trigger)
# works as 4+left or left+4 (all of the examples do)

You seem smart enough to figure out the rest from there.

2 of 3
2

Beware, language may play a role! In my case the 'up' arrow was translated to my local language, you can run the following code to get the key value for your computer:

import keyboard    
def onkeypress(event):
    print(event.name)

keyboard.on_press(onkeypress)

#Use ctrl+c to stop
while True:
    pass
๐ŸŒ
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
Use key press and key release events supplied by the toolkit (KEYDOWN/KeyPress/on_key_down) and compare against the frameworkโ€™s arrow-key constants. ... You can also use pyglet. The on_key_press() and on_key_release() events are fired when any key on the keyboard is pressed or released, respectively.
๐ŸŒ
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
๐ŸŒ
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: ...rom-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....
Find elsewhere
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)
๐ŸŒ
YouTube
youtube.com โ€บ codemore
how to use arrow keys in python - YouTube
Download this code from https://codegive.com Title: Using Arrow Keys in Python: A Tutorial with Code ExamplesIntroduction:Arrow keys play a crucial role in u...
Published ย  December 20, 2023
Views ย  594
๐ŸŒ
Python Forum
python-forum.io โ€บ thread-33763.html
Using Keyboard Arrow Keys
May 25, 2021 - How can I user keyboard arrows keys to move the catcher (box in the game) to the right and left? Thanks. # Bomb Catcher Game import sys, random, time, pygame from pygame.locals import * def print_text(font, x, y, text, color=(255,255,255)): ...
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.

๐ŸŒ
w3resource
w3resource.com โ€บ python-exercises โ€บ tkinter โ€บ python-tkinter-events-and-event-handling-exercise-12.php
Python Tkinter arrow key game - Character movement example
August 25, 2025 - Learn how to create a Python program using Tkinter to build a simple game where a character moves in response to arrow key presses. Implement event handling for left, right, up, and down arrow keys.
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.

๐ŸŒ
Reddit
reddit.com โ€บ r/learnpython โ€บ does the keyboard library work with arrow keys?
r/learnpython on Reddit: Does the keyboard library work with arrow keys?
December 14, 2023 -

I'm making a code to take a simulate a press key when a certain color is detected, now I've made the code up until I started to integrate the keyboard library.

Does the library work with arrow keys?

Since I'm not getting any response out of them unfortunately. Tried with other keys and functions and it works just fine.This is one of my snippets:

if right_arrow[0] == 176 and right_flag == 0: 
print("right") keyboard.press_and_release('right') 
right_flag = 1

Am I doing something wrong?

๐ŸŒ
PyAutoGUI
pyautogui.readthedocs.io โ€บ en โ€บ latest โ€บ keyboard.html
Keyboard Control Functions โ€” PyAutoGUI documentation
To press these keys, call the press() function and pass it a string from the pyautogui.KEYBOARD_KEYS such as enter, esc, f1. See KEYBOARD_KEYS. ... >>> pyautogui.press('enter') # press the Enter key >>> pyautogui.press('f1') # press the F1 key >>> pyautogui.press('left') # press the left arrow key
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
๐ŸŒ
Raspberry Pi Forums
forums.raspberrypi.com โ€บ board index โ€บ programming โ€บ python
python arrow control - Raspberry Pi Forums
try: while not done: char = screen.getch() if char == ord('q'): end_code() elif char == curses.KEY_RIGHT: # print doesn't work with curses, use addstr instead turn_right() elif char == curses.KEY_LEFT: turn_left() elif char == curses.KEY_UP: forwards() elif char == curses.KEY_DOWN: backwards() elif char != curses.KEY_UP and char != curses.KEY_DOWN: still() elif char != curses.KEY_LEFT and char != curses.KEY_RIGHT: straight() thanks Mat edit- corrected some syntax errors, still not working
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ 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".