¿Cómo hago que Python espere una tecla presionada?


571

Quiero que mi script espere hasta que el usuario presione cualquier tecla.

¿Cómo puedo hacer eso?

Respuestas:


543

En Python 3 use input():

input("Press Enter to continue...")

En Python 2 use raw_input():

raw_input("Press Enter to continue...")

Sin embargo, esto solo espera a que el usuario presione enter.

Es posible que desee usar msvcrt ((solo Windows / DOS) El módulo msvcrt le da acceso a una serie de funciones en la Biblioteca de tiempo de ejecución de Microsoft Visual C / C ++ (MSVCRT):

import msvcrt as m
def wait():
    m.getch()

Esto debería esperar a que se presione una tecla.

Información adicional:

en Python 3 raw_input()no existe

En Python 2 input(prompt)es equivalente aeval(raw_input(prompt))


54
Recibo este error cuando intento hacer esto en Python 2.7: "SyntaxError: EOF inesperado al analizar"
Jon Tirsen

8
@ Solarsaturn9 y un número creciente y grande no lo hacen. Por lo tanto, esta respuesta no funcionó para mí y las muchas otras que vienen aquí.
ctrl-alt-delor

55
@richard usando input () también debería funcionar en otras plataformas. Es ridículo acoplar puntos para proporcionar una solución alternativa única de Windows cuando la primera solución es multiplataforma.
Cory Buckley

77
@ Solarsaturn9 lee la pregunta y responde de nuevo: inputno continúa si se presiona alguna tecla, solo si se presiona enter.
ctrl-alt-delor

13
@JonTirsen es porque Python 2.7 tiene una función llamada input que evalúa la cadena que ingresas. Para solucionarlo, use raw_input
Samy Bencherif

316

Una forma de hacer esto en Python 2 es usar raw_input():

raw_input("Press Enter to continue...")

En python3 es solo input()


17
¿Qué pasa cuando puede ser una de varias claves? No solo enter?
noio

33
Con Python 3+ , esto ha cambiado a solo input().
palswim

Usando seis para el código compatible Py2 y Py3:from six.moves import input; input("Press Enter to continue...")
rcoup

56

En mi caja de Linux, uso el siguiente código. Esto es similar al código que he visto en otros lugares (por ejemplo, en las preguntas frecuentes anteriores de Python), pero ese código gira en un bucle cerrado donde este código no lo hace y hay muchos casos de esquinas extrañas que el código no tiene en cuenta. El código lo hace.

def read_single_keypress():
    """Waits for a single keypress on stdin.

    This is a silly function to call if you need to do it a lot because it has
    to store stdin's current setup, setup stdin for reading single keystrokes
    then read the single keystroke then revert stdin back after reading the
    keystroke.

    Returns a tuple of characters of the key that was pressed - on Linux, 
    pressing keys like up arrow results in a sequence of characters. Returns 
    ('\x03',) on KeyboardInterrupt which can happen when a signal gets
    handled.

    """
    import termios, fcntl, sys, os
    fd = sys.stdin.fileno()
    # save old state
    flags_save = fcntl.fcntl(fd, fcntl.F_GETFL)
    attrs_save = termios.tcgetattr(fd)
    # make raw - the way to do this comes from the termios(3) man page.
    attrs = list(attrs_save) # copy the stored version to update
    # iflag
    attrs[0] &= ~(termios.IGNBRK | termios.BRKINT | termios.PARMRK
                  | termios.ISTRIP | termios.INLCR | termios. IGNCR
                  | termios.ICRNL | termios.IXON )
    # oflag
    attrs[1] &= ~termios.OPOST
    # cflag
    attrs[2] &= ~(termios.CSIZE | termios. PARENB)
    attrs[2] |= termios.CS8
    # lflag
    attrs[3] &= ~(termios.ECHONL | termios.ECHO | termios.ICANON
                  | termios.ISIG | termios.IEXTEN)
    termios.tcsetattr(fd, termios.TCSANOW, attrs)
    # turn off non-blocking
    fcntl.fcntl(fd, fcntl.F_SETFL, flags_save & ~os.O_NONBLOCK)
    # read a single keystroke
    ret = []
    try:
        ret.append(sys.stdin.read(1)) # returns a single character
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save | os.O_NONBLOCK)
        c = sys.stdin.read(1) # returns a single character
        while len(c) > 0:
            ret.append(c)
            c = sys.stdin.read(1)
    except KeyboardInterrupt:
        ret.append('\x03')
    finally:
        # restore old state
        termios.tcsetattr(fd, termios.TCSAFLUSH, attrs_save)
        fcntl.fcntl(fd, fcntl.F_SETFL, flags_save)
    return tuple(ret)

Si bien este es mi favorito de las respuestas aquí, al igual que los demás no coger cosas como cambio, control, etc
Mala

1
@Mala que prácticamente no es posible en Python puro; tal vez deberías escribir un módulo C?
gato

Recibo "\ x03" en la interrupción del teclado (Ctrl-C) en mi sistema.
RDA

1
ctrl-c es un ascii 3, por lo que se espera. Si desea elevar una señal en ctrl-c, la solución fácil es poner un if ord (return_value) == 3: os.kill (os.getpid (), signal.SIGINT) pero también puede desactivar el procesamiento de la señal por attrs [0] | = termios.BRKINT, attrs [3]! = termios.ISIG, y deshacerse del procesamiento excepto KeyboardInterrupt. Nota: Cambié el valor de retorno de KeyboardInterrupt en '\ x03' en honor a su consulta (y porque eso hace que este código siempre devuelva una cadena).
mheyman

¿Cómo podría ajustarse el código anterior para que devuelva una tupla para una pulsación de tecla compleja como "Re Pág" o "Flecha izquierda"?
Derek

33

Si está de acuerdo con los comandos del sistema, puede usar lo siguiente:

Linux:

import os
os.system('read -sn 1 -p "Press any key to continue..."')
print

Ventanas:

import os
os.system("pause")

Si desea seguir ejecutándose hasta que se genere una señal (como SIGINT), también puede verificar el valor de retorno systemy luego llamar sys.exit(0).
James Taylor

29

Simplemente usando

input("Press Enter to continue...")

causará un SyntaxError: EOF esperado durante el análisis.

Uso de arreglo simple:

try:
    input("Press enter to continue")
except SyntaxError:
    pass

55
No lo use inputen python 2: la función correcta es raw_input. En python 2, inputes equivalente a eval(raw_input()).
Blorgbeard sale el

2
Esto ignora todas las teclas que el usuario presiona, hasta que presiona enter, lo cual es bastante diferente de lo que está pidiendo el OP.
Jonathan Hartley

1
Además, si iba a usar 'input', no es apropiado atrapar un SyntaxError. Cualquiera que sea el tipo de usuario que se evalúa, por lo que si, por ejemplo, escribe "1/0", se genera un ZeroDivisionError en lugar de un SyntaxError y el programa se cerrará.
Jonathan Hartley

Como mencionó @Blorgbeard, basta con usar raw_input ("Presione Entrar para continuar ...") será suficiente. Lo uso a menudo ahora cuando depuro.
2015

15

El manual de Python proporciona lo siguiente:

import termios, fcntl, sys, os
fd = sys.stdin.fileno()

oldterm = termios.tcgetattr(fd)
newattr = termios.tcgetattr(fd)
newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
termios.tcsetattr(fd, termios.TCSANOW, newattr)

oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)

try:
    while 1:
        try:
            c = sys.stdin.read(1)
            print "Got character", repr(c)
        except IOError: pass
finally:
    termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)

que se puede incluir en su caso de uso.


12
Es una buena práctica copiar lo que está enlazando para que el conocimiento permanezca, incluso si el enlace desaparece (¡y lo hacen!).
Richard

1
¿Cómo puedo hacer que esto funcione en Python 3.x? En 3.x, después de cambiar la declaración de impresión para que sea compatible, esto simplemente se repite infinitamente y no espera la entrada. Sin embargo, funciona muy bien en Python 2.
gato

El enlace ha sido actualizado para redirigir a una página diferente. El nuevo enlace está aquí.
Matthias

15

Plataforma cruzada, código Python 2/3:

# import sys, os

def wait_key():
    ''' Wait for a key press on the console and return it. '''
    result = None
    if os.name == 'nt':
        import msvcrt
        result = msvcrt.getch()
    else:
        import termios
        fd = sys.stdin.fileno()

        oldterm = termios.tcgetattr(fd)
        newattr = termios.tcgetattr(fd)
        newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO
        termios.tcsetattr(fd, termios.TCSANOW, newattr)

        try:
            result = sys.stdin.read(1)
        except IOError:
            pass
        finally:
            termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)

    return result

Eliminé el material fctl / sin bloqueo porque estaba dando IOErrorsy no lo necesitaba. Estoy usando este código específicamente porque quiero que se bloquee. ;)

Apéndice:

Implementé esto en un paquete en PyPI con muchas otras cosas llamadas consola :

>>> from console.utils import wait_key

>>> wait_key()
'h'

1
Recibí un error: ioctl inapropiado para el dispositivo '
Benoit

@Benoit qué sistema operativo?
Gringo Suave

Linux - Ubuntu 20.04
Benoit

14

No conozco una forma independiente de plataforma de hacerlo, pero en Windows, si usa el módulo msvcrt, puede usar su función getch:

import msvcrt
c = msvcrt.getch()
print 'you entered', c

mscvcrt también incluye la función kbhit () sin bloqueo para ver si se presionó una tecla sin esperar (no estoy seguro si hay una función de maldición correspondiente). Bajo UNIX, está el paquete curses, pero no estoy seguro si puede usarlo sin usarlo para toda la salida de la pantalla. Este código funciona bajo UNIX:

import curses
stdscr = curses.initscr()
c = stdscr.getch()
print 'you entered', chr(c)
curses.endwin()

Tenga en cuenta que curses.getch () devuelve el ordinal de la tecla presionada para que tenga la misma salida que tuve que lanzar.


Usar maldiciones es mucho mejor que los ejemplos bastante complicados descritos en el manual, incluso si implica una gran dependencia. +1
Damián

4

Si desea esperar para ingresar (para que el usuario golpee el teclado no provoque que suceda algo inesperado) use

sys.stdin.readline()

2
El objetivo es que el usuario no tenga que presionar solo la tecla Intro, por ejemplo, para poder simplemente golpear la barra espaciadora. Si necesita Enter para evitar que suceda algo involuntario, entonces ese es un mal diseño.
Synetech

3

Soy nuevo en Python y ya estaba pensando que soy demasiado estúpido para reproducir las sugerencias más simples hechas aquí. Resulta que hay una trampa que uno debería saber:

Cuando se ejecuta un script python desde IDLE, algunos comandos IO parecen comportarse de manera completamente diferente (ya que en realidad no hay una ventana de terminal).

P.ej. msvcrt.getch no bloquea y siempre devuelve $ ff. Esto ya se informó hace mucho tiempo (ver, por ejemplo, https://bugs.python.org/issue9290 ), y está marcado como solucionado, de alguna manera el problema parece persistir en las versiones actuales de python / IDLE.

Entonces, si alguno de los códigos publicados anteriormente no funciona para usted, intente ejecutar el script manualmente y NO desde IDLE .


0

Si desea ver si presionaron una tecla exacta (como decir 'b') Haga esto:

while True:
    choice = raw_input("> ")

    if choice == 'b' :
        print "You win"
        input("yay")
        break

8
Esto requiere que el usuario escriba 'b' (u otra cosa) y luego presione Intro, que es bastante diferente de lo que solicita el OP.
Jonathan Hartley

0

os.system parece invocar siempre sh, que no reconoce las opciones syn para leer. Sin embargo, el comando de lectura se puede pasar a bash:

 os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")

2
La documentación leída me hace pensar que no expirará a menos que especifique la opción -t.
James King
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.