Como faço para o python esperar por uma tecla pressionada?

571

Quero que meu script aguarde até que o usuário pressione qualquer tecla.

Como faço isso?

Janusz
fonte

Respostas:

543

No Python 3, use input():

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

No Python 2, use raw_input():

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

Isso espera apenas que o usuário pressione enter.

Pode-se usar o msvcrt ((somente Windows / DOS) O módulo msvcrt fornece acesso a várias funções na Biblioteca de Tempo de Execução do Microsoft Visual C / C ++ (MSVCRT):

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

Isso deve esperar por um pressionamento de tecla.

Informação adicional:

no Python 3 raw_input()não existe

No Python 2 input(prompt)é equivalente aeval(raw_input(prompt))

riza
fonte
54
Estou recebendo esse erro quando tento fazer isso no Python 2.7: "SyntaxError: EOF inesperado durante a análise"
Jon Tirsen
8
@ Solarsaturn9 e um número crescente e grande não. Portanto, essa resposta não funcionou para mim e para as muitas outras que vêm aqui.
ctrl-alt-delor 22/10/2015
5
@richard usando input () também deve funcionar em outras plataformas. É ridículo atracar pontos por fornecer uma solução alternativa apenas para Windows quando a primeira solução é multiplataforma.
Cory Buckley
7
@ Solarsaturn9 leia a pergunta e responda novamente: inputnão continua se qualquer tecla for pressionada, apenas se pressionar Enter.
Ctrl-alt-delor 23/10/2015
13
@ JonTirsen é porque o Python 2.7 tem uma função chamada input que avalia a string que você digita. Para corrigir, use raw_input
Samy
316

Uma maneira de fazer isso no Python 2 é usar raw_input():

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

Em python3 é apenas input()

Greg Hewgill
fonte
17
E quando pode ser uma das várias chaves? Não é só enter?
Noio
33
Com o Python 3+ , isso mudou para apenas input().
palswim
Usando seis para Py2 & PY3 código compatível:from six.moves import input; input("Press Enter to continue...")
rcoup
56

Na minha caixa linux, eu uso o seguinte código. Isso é semelhante ao código que eu já vi em outros lugares (nas FAQs antigas sobre python, por exemplo), mas esse código gira em um loop apertado, onde esse código não existe e há muitos casos de canto estranhos em que o código não explica isso. código faz.

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)
mheyman
fonte
Enquanto este é o meu favorito das respostas aqui, como os outros não pegar coisas como mudança, controle, etc
Mala
1
@ Malala que praticamente não é possível em Python puro; talvez você deva escrever um módulo C?
cat
Estou recebendo "\ x03" na interrupção do teclado (Ctrl-C) no meu sistema.
GDR
1
ctrl-c é um ascii 3, portanto é esperado. Se você deseja aumentar um sinal em ctrl-c, a solução mais fácil é colocar um if ord (valor_ retornado) == 3: os.kill (os.getpid (), signal.SIGINT), mas também pode desativar o processamento de sinal por attrs [0] | = termios.BRKINT, attrs [3]! = termios.ISIG e livre-se do processamento, exceto KeyboardInterrupt. Nota - Alterei o valor de retorno de KeyboardInterrupt para '\ x03' em homenagem à sua consulta (e porque isso faz com que esse código sempre retorne uma string).
precisa saber é
Como o código acima pode ser ajustado para retornar uma tupla para um pressionamento de tecla complexo como "Page Up" ou "Seta para a esquerda"?
Derek
33

Se você concorda com os comandos do sistema, pode usar o seguinte:

Linux:

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

Janelas:

import os
os.system("pause")
CrouZ
fonte
Se você quiser continuar funcionando até que um sinal seja gerado (como SIGINT), você também pode verificar o valor de retorno systeme depois ligar sys.exit(0).
James Taylor
29

Simplesmente usando

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

causará um SyntaxError: EOF esperado durante a análise.

Uso de correção simples:

try:
    input("Press enter to continue")
except SyntaxError:
    pass
Tudo verdade
fonte
5
Não use inputno python 2 - a função correta é raw_input. No python 2, inputé equivalente a eval(raw_input()).
Blorgbeard sai
2
Isso ignora todas as teclas que o usuário pressiona, até que pressione Enter, o que é bem diferente do que o OP está pedindo.
Jonathan Hartley
1
Além disso, se você fosse usar 'input', capturar um SyntaxError não é apropriado. Qualquer que seja o tipo de usuário avaliado, portanto, se, por exemplo, digitar "1/0", um ZeroDivisionError será gerado em vez de um SyntaxError, e seu programa será encerrado.
Jonathan Hartley
Como o @Blorgbeard mencionou, basta usar raw_input ("Pressione Enter para continuar ...") será suficiente. Eu o uso frequentemente agora ao depurar.
alltrue 27/08/15
15

O manual python fornece o seguinte:

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 pode ser acumulado no seu caso de uso.

Jaap Versteegh
fonte
12
É uma boa prática copiar o que você está vinculando para que o conhecimento permaneça, mesmo que o link morra (e eles acabam!).
Richard
1
Como posso fazer isso funcionar no Python 3.x? Na 3.x, depois de alterar a declaração de impressão para ser compatível, isso faz um loop infinito e não espera pela entrada. Funciona muito bem no Python 2, no entanto.
cat
O link foi atualizado para redirecionar para uma página diferente. O novo link está aqui.
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

Eu removi o material fctl / non-blocking porque estava dando IOErrors e não precisava dele. Estou usando esse código especificamente porque quero que ele bloqueie. ;)

Termo aditivo:

Eu implementei isso em um pacote no PyPI com muitos outros itens chamados console :

>>> from console.utils import wait_key

>>> wait_key()
'h'
Gringo Suave
fonte
1
Erro: ioctl inadequado para o dispositivo '
Benoit
@Benoit qual SO?
Gringo Suave
Linux - Ubuntu 20.04
Benoit
14

Não conheço uma maneira independente de fazê-lo, mas no Windows, se você usar o módulo msvcrt, poderá usar a função getch:

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

O mscvcrt também inclui a função kbhit () sem bloqueio para verificar se uma tecla foi pressionada sem aguardar (não tenho certeza se há uma função de maldições correspondente). No UNIX, existe o pacote maldições, mas não tenho certeza se você pode usá-lo sem usá-lo para toda a saída da tela. Este código funciona no UNIX:

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

Observe que curses.getch () retorna o ordinal da tecla pressionada, para que ela tenha a mesma saída que eu tive para convertê-la.

John Gaines Jr.
fonte
Usar maldições é muito melhor do que os exemplos bastante complicados descritos pelo manual, mesmo que envolva uma enorme dependência. +1
Damian
4

Se você deseja aguardar a entrada (para que o usuário toque no teclado não faça com que algo não intencional aconteça), use

sys.stdin.readline()
andrew pate
fonte
2
O ponto principal é que o usuário não precisa pressionar apenas a tecla Enter, para, por exemplo, poder dar um tapa na barra de espaço. Se você precisar do Enter para evitar que algo não intencional aconteça, será um projeto ruim.
Synetech 5/09/19
3

Eu sou novo no python e já estava pensando que sou burro demais para reproduzir as sugestões mais simples feitas aqui. Acontece que há uma armadilha que se deve saber:

Quando um script python é executado a partir do IDLE, alguns comandos de E / S parecem se comportar completamente diferentes (como na verdade não há janela de terminal).

Por exemplo. O msvcrt.getch é sem bloqueio e sempre retorna $ ff. Isso já foi relatado há muito tempo (veja, por exemplo, https://bugs.python.org/issue9290 ) - e está marcado como corrigido, de alguma forma o problema parece persistir nas versões atuais do python / IDLE.

Portanto, se algum código postado acima não funcionar, tente executar o script manualmente e NÃO a partir do IDLE .

ralfiii
fonte
0

Se você quiser ver se eles pressionaram uma tecla exata (como digamos 'b'), faça o seguinte:

while True:
    choice = raw_input("> ")

    if choice == 'b' :
        print "You win"
        input("yay")
        break
E40
fonte
8
Isso requer que o usuário digite 'b' (ou outra coisa) e pressione enter, que é bem diferente do que o OP está solicitando.
Jonathan Hartley
0

o os.system parece sempre chamar sh, que não reconhece as opções s e n para leitura. No entanto, o comando read pode ser passado para o bash:

 os.system("""bash -c 'read -s -n 1 -p "Press any key to continue..."'""")
James King
fonte
2
A documentação lida me faz pensar que não atingirá o tempo limite, a menos que você especifique a opção -t.
James King