raw_input in python without pressing enter

Posted on

Question :

raw_input in python without pressing enter

I’m using raw_input in Python to interact with user in shell.

c = raw_input('Press s or n to continue:')
if c.upper() == 'S':
    print 'YES'

It works as intended, but the user has to press enter in the shell after pressing ‘s’. Is there a way to accomplish what I need from an user input without needing to press enter in the shell? I’m using *nixes machines.

Answer #1:

Under Windows, you need the msvcrt module, specifically, it seems from the way you describe your problem, the function msvcrt.getch:

Read a keypress and return the
resulting character. Nothing is echoed
to the console. This call will block
if a keypress is not already
available, but will not wait for Enter
to be pressed.

(etc — see the docs I just pointed to). For Unix, see e.g. this recipe for a simple way to build a similar getch function (see also several alternatives &c in the comment thread of that recipe).

Answer #2:

Python does not provide a multiplatform solution out of the box.
If you are on Windows you could try msvcrt with:

import msvcrt
print 'Press s or n to continue:n'
input_char = msvcrt.getch()
if input_char.upper() == 'S': 
   print 'YES'
Answered By: Alex Martelli

Answer #3:

curses can do that as well :

import curses, time

def input_char(message):
    try:
        win = curses.initscr()
        win.addstr(0, 0, message)
        while True: 
            ch = win.getch()
            if ch in range(32, 127): 
                break
            time.sleep(0.05)
    finally:
        curses.endwin()
    return chr(ch)

c = input_char('Do you want to continue? y/[n]')
if c.lower() in ['y', 'yes']:
    print('yes')
else:
    print('no (got {})'.format(c))
Answered By: systempuntoout

Answer #4:

Actually in the meantime (almost 10 years from the start of this thread) a cross-platform module named pynput appeared.
Below a first cut – i.e. that works with lowercase ‘s’ only.
I have tested it on Windows but I am almost 100% positive that it should work on Linux.

from pynput import keyboard

print('Press s or n to continue:')

with keyboard.Events() as events:
    # Block for as much as possible
    event = events.get(1e6)
    if event.key == keyboard.KeyCode.from_char('s'):
        print("YES")
Answered By: user2660966

Answer #5:

Instead of the msvcrt module you could also use WConio:

>>> import WConio
>>> ans = WConio.getkey()
>>> ans
'y'
Answered By: Adrian Rosoga

Answer #6:

To get a single character, I have used getch, but I don’t know if it works on Windows.

Answered By: John Howard

Answer #7:

On a side note, msvcrt.kbhit() returns a boolean value determining if any key on the keyboard is currently being pressed.

So if you’re making a game or something and want keypresses to do things but not halt the game entirely, you can use kbhit() inside an if statement to make sure that the key is only retrieved if the user actually wants to do something.

An example in Python 3:

# this would be in some kind of check_input function
if msvcrt.kbhit():
    key = msvcrt.getch().decode("utf-8").lower() # getch() returns bytes data that we need to decode in order to read properly. i also forced lowercase which is optional but recommended
    if key == "w": # here 'w' is used as an example
        # do stuff
    elif key == "a":
        # do other stuff
    elif key == "j":
        # you get the point
Answered By: Derek Kurth

Answer #8:

I know this is old, but the solution wasn’t good enough for me.
I need the solution to support cross-platform and without installing any external Python packages.

My solution for this, in case anyone else comes across this post

Reference: https://github.com/unfor19/mg-tools/blob/master/mgtools/get_key_pressed.py

from tkinter import Tk, Frame


def __set_key(e, root):
    """
    e - event with attribute 'char', the released key
    """
    global key_pressed
    if e.char:
        key_pressed = e.char
        root.destroy()


def get_key(msg="Press any key ...", time_to_sleep=3):
    """
    msg - set to empty string if you don't want to print anything
    time_to_sleep - default 3 seconds
    """
    global key_pressed
    if msg:
        print(msg)
    key_pressed = None
    root = Tk()
    root.overrideredirect(True)
    frame = Frame(root, width=0, height=0)
    frame.bind("<KeyRelease>", lambda f: __set_key(f, root))
    frame.pack()
    root.focus_set()
    frame.focus_set()
    frame.focus_force()  # doesn't work in a while loop without it
    root.after(time_to_sleep * 1000, func=root.destroy)
    root.mainloop()
    root = None  # just in case
    return key_pressed


def __main():
        c = None
        while not c:
                c = get_key("Choose your weapon ... ", 2)
        print(c)

if __name__ == "__main__":
    __main()
Answered By: Nytra

Leave a Reply

Your email address will not be published. Required fields are marked *