Existe uma maneira de ler um único caractere da entrada do usuário? Por exemplo, eles pressionam uma tecla no terminal e ela é retornada (mais ou menos como getch()
). Eu sei que há uma função no Windows para isso, mas eu gostaria de algo que seja multiplataforma.
262
msvcrt.getch
pormsvcrt.getwch
, como sugerido lá.Respostas:
Aqui está um link para um site que diz como você pode ler um único caractere no Windows, Linux e OSX: http://code.activestate.com/recipes/134892/
fonte
ImportError
exceção é usada como algum tipo de declaração if; por que não chamar platform.system () para verificar o sistema operacional?lerá basicamente 1 byte do STDIN.
Se você deve usar o método que não espera,
\n
você pode usar este código como sugerido na resposta anterior:( extraído de http://code.activestate.com/recipes/134892/ )
fonte
A receita do ActiveState citada literalmente em duas respostas é exagerada. Pode-se resumir a isso:
fonte
0
.Também vale a pena tentar é a biblioteca readchar , que é parcialmente baseada na receita do ActiveState mencionada em outras respostas.
Instalação:
Uso:
Testado no Windows e Linux com Python 2.7.
No Windows, somente as chaves que são mapeados para letras ou códigos de controle ASCII são suportados ( Backspace, Enter, Esc, Tab, Ctrl+ letra ). No GNU / Linux (dependendo do terminal exata, talvez?) Você também terá Insert, Delete, Pg Up, Pg Dn, Home, Ende teclas ... mas, em seguida, há questões que separam estas teclas especiais de um .F nEsc
Advertência: Como com a maioria (?) Todas as respostas aqui, chaves de sinal como Ctrl+ C, Ctrl+ De Ctrl+ Zsão capturados e devolvidos (como
'\x03'
,'\x04'
e'\x1a'
respectivamente); pode ser difícil abortar seu programa.fonte
Um método alternativo:
A partir deste post .
fonte
| os.O_NONBLOCK
. Caso contrário, você pode colocá-lo em um loop (é uma boa idéia dormir um pouco no loop para não girar).while True
entãowhile 1
.Esse código, baseado aqui , aumentará corretamente KeyboardInterrupt e EOFError se Ctrl+ Cou Ctrl+ Dforem pressionados.
Deve funcionar no Windows e Linux. Uma versão do OS X está disponível na fonte original.
fonte
A resposta (atualmente) com a melhor classificação (com o código ActiveState) é muito complicada. Não vejo uma razão para usar classes quando uma mera função deve ser suficiente. Abaixo estão duas implementações que realizam a mesma coisa, mas com código mais legível.
Ambas as implementações:
Versão 1: legível e simples
Versão 2: evite importações repetidas e manipulação de exceções:
[EDIT] Perdi uma vantagem do código do ActiveState. Se você planeja ler caracteres várias vezes, esse código evita o custo (desprezível) de repetir a importação do Windows e o tratamento de exceção ImportError em sistemas semelhantes ao Unix. Embora você provavelmente deva se preocupar mais com a legibilidade do código do que com a otimização insignificante, aqui está uma alternativa (é semelhante à resposta de Louis, mas getChar () é independente) que funciona da mesma forma que o código ActiveState e é mais legível:
Código de exemplo que exercita uma das versões getChar () acima:
fonte
Este pode ser um caso de uso para um gerenciador de contexto. Deixando de lado os subsídios para o sistema operacional Windows, aqui está minha sugestão:
fonte
self
em__enter__
e ter umread
método que retornasys.stdin.read(1)
, então você pode ler vários personagens em um contexto.Tente usar o seguinte: http://home.wlu.edu/~levys/software/kbhit.py É sem bloqueio (isso significa que você pode ter um loop while e detectar um pressionamento de tecla sem parar) e em várias plataformas.
Um exemplo para usar isso:
Ou você pode usar o módulo getch do PyPi . Mas isso bloquearia o loop while
fonte
É NÃO-BLOQUEIO, lê uma chave e a armazena em keypress.key.
no seu programa
fonte
As respostas aqui foram informativas, no entanto, eu também queria uma maneira de pressionar as teclas de forma assíncrona e acionar as teclas em eventos separados, tudo de maneira segura e em várias plataformas. PyGame também estava inchado demais para mim. Então fiz o seguinte (no Python 2.7, mas suspeito que seja facilmente portátil), que achei que compartilharia aqui caso fosse útil para qualquer outra pessoa. Guardei isso em um arquivo chamado keyPress.py.
A idéia é que você pode simplesmente ligar
keyPress.getKey()
, que lerá uma tecla do teclado e depois retornará.Se você quer algo mais que isso, eu fiz um
KeyCapture
objeto. Você pode criar um via algo comokeys = keyPress.KeyCapture()
.Depois, há três coisas que você pode fazer:
addEvent(functionName)
aceita qualquer função que aceite um parâmetro. Então, toda vez que uma tecla for pressionada, essa função será chamada com a string da tecla conforme for inserida. Eles são executados em um encadeamento separado, para que você possa bloquear tudo o que deseja e não atrapalhará a funcionalidade do KeyCapturer nem atrasará os outros eventos.get()
retorna uma chave da mesma maneira que o bloqueio anterior. Agora é necessário aqui, porque as chaves estão sendo capturadas por meio doKeyCapture
objeto agora, portanto,keyPress.getKey()
entrariam em conflito com esse comportamento e os dois perderiam algumas chaves, pois apenas uma chave pode ser capturada por vez. Diga também que o usuário pressiona 'a', depois 'b', você chamaget()
, o usuário pressiona 'c'. Essaget()
chamada retornará imediatamente 'a'; se você ligar novamente, retornará 'b'; depois, 'c'. Se você ligar novamente, ele bloqueará até que outra tecla seja pressionada. Isso garante que você não perca nenhuma chave, de maneira bloqueadora, se desejar. Portanto, dessa maneira, é um pouco diferente do quekeyPress.getKey()
antesSe você deseja o comportamento de
getKey()
voltar,get(lossy=True)
é comoget()
, exceto que ele só retorna as teclas pressionadas após a chamada paraget()
. Portanto, no exemplo acima,get()
seria bloqueado até o usuário pressionar 'c' e, se você chamá-lo novamente, ele bloqueará até que outra tecla seja pressionada.getAsync()
é um pouco diferente. Ele foi projetado para algo que processa muito e, ocasionalmente, volta e verifica quais teclas foram pressionadas. Assim,getAsync()
retorna uma lista de todas as teclas pressionadas desde a última chamada paragetAsync()
, na ordem da tecla mais antiga para a tecla mais recente pressionada. Também não é bloqueado, o que significa que, se nenhuma tecla foi pressionada desde a última chamadagetAsync()
, um vazio[]
será retornado.Para realmente começar a capturar as chaves, você precisa ligar
keys.startCapture()
com o seukeys
objeto feito acima.startCapture
é não-bloqueante e simplesmente inicia um segmento que registra apenas as teclas pressionadas e outro para processar essas teclas. Existem dois threads para garantir que o thread que registra pressionamentos de tecla não perca nenhuma tecla.Se você deseja parar de capturar chaves, pode ligar
keys.stopCapture()
e ele irá parar de capturar chaves. No entanto, como capturar uma chave é uma operação de bloqueio, as chaves de captura de encadeamento podem capturar mais uma chave após a chamadastopCapture()
.Para evitar isso, você pode passar um (s) parâmetro (s) opcional (s) para
startCapture(functionName, args)
uma função que faz algo como checa se uma tecla é igual a 'c' e sai. É importante que essa função faça muito pouco antes, por exemplo, dormir aqui nos fará perder as teclas.No entanto, se
stopCapture()
for chamada nesta função, as capturas de teclas serão interrompidas imediatamente, sem tentar capturar mais, e todas asget()
chamadas serão retornadas imediatamente, com None se nenhuma tecla tiver sido pressionada ainda.Além disso, desde
get()
egetAsync()
armazenar todas as teclas anteriores pressionadas (até recuperá-las), você pode ligarclearGetList()
eclearAsyncList()
esquecer as teclas pressionadas anteriormente.Observe que
get()
,getAsync()
e os eventos são independentes, portanto, se uma tecla for pressionada: 1. Uma chamada paraget()
a espera, com perdas ativadas, retornará a tecla. As outras chamadas em espera (se houver) continuarão em espera. 2. Essa tecla será armazenada na fila de teclas get, para que,get()
com perdas desligadas, retorne a tecla mais antiga pressionada ainda não retornadaget()
. 3. Todos os eventos serão acionados com essa chave como entrada. 4. Essa chave será armazenada na lista degetAsync()
chaves, em que a lis será retornada e configurada como lista vazia na próxima chamada paragetAsync()
Se tudo isso for demais, aqui está um exemplo de caso de uso:
Está funcionando bem para mim desde o teste simples que fiz, mas terei todo o prazer em receber feedback de outras pessoas se houver algo que eu perdi.
Eu postei isso aqui também.
fonte
Um comentário em uma das outras respostas mencionou o modo de quebra, o que é importante para implementações do Unix, porque geralmente você não deseja que ^ C (
KeyboardError
) seja consumido pelo getchar (como será quando você definir o terminal no modo bruto, como feito por outras respostas).Outro detalhe importante é que, se você deseja ler um caractere e não um byte , deve ler 4 bytes do fluxo de entrada, pois esse é o número máximo de bytes em que um único caractere será composto em UTF-8 (Python 3+ ) A leitura de apenas um byte produzirá resultados inesperados para caracteres de vários bytes, como setas do teclado.
Aqui está minha implementação alterada para Unix:
fonte
Tente isso com pygame:
fonte
pygame.error: video system not initialized
A receita do ActiveState parece conter um pequeno bug para sistemas "posix" que impede a
Ctrl-C
interrupção (estou usando o Mac). Se eu colocar o seguinte código no meu script:Nunca poderei terminar o script
Ctrl-C
e preciso matar meu terminal para escapar.Eu acredito que a seguinte linha é a causa, e também é muito brutal:
Além disso, o pacote
tty
não é realmente necessário,termios
é suficiente para lidar com isso.Abaixo está o código aprimorado que funciona para mim (
Ctrl-C
interromperá), com agetche
função extra que ecoa o char enquanto você digita:Referências:
fonte
O
curses
pacote em python pode ser usado para entrar no modo "bruto" para entrada de caracteres do terminal com apenas algumas instruções. O principal uso das maldições é assumir o controle da tela, o que pode não ser o que você deseja. Emprint()
vez disso, esse trecho de código usa instruções que são utilizáveis, mas você deve estar ciente de como as maldições alteram as terminações de linha associadas à saída.fonte
Se estou fazendo algo complicado, usarei maldições para ler as chaves. Mas muitas vezes eu só quero um script Python 3 simples que use a biblioteca padrão e possa ler teclas de seta, então faço isso:
fonte
Minha solução para python3, não depende de nenhum pacote de pip.
fonte
Eu acredito que esta é uma das soluções mais elegantes.
e depois use-o no código:
fonte
A resposta aceita não funcionou tão bem para mim (eu segurei uma tecla, nada aconteceria, depois pressionei outra tecla e funcionaria).
Depois de aprender sobre o módulo de maldições , parece realmente o caminho certo a seguir. E agora está disponível para Windows através de cursores do Windows (disponível através do pip), para que você possa programar de maneira independente da plataforma. Aqui está um exemplo inspirado neste bom tutorial no YouTube:
Salve-o com uma
.py
extensão ou executecurses.wrapper(getkey)
no modo interativo.fonte
Respondida aqui: raw_input em python sem pressionar enter
Use este código
Referência: https://github.com/unfor19/mg-tools/blob/master/mgtools/get_key_pressed.py
fonte
Se você deseja registrar apenas uma única tecla, pressione mesmo que o usuário tenha pressionado por mais de uma vez ou tenha mantido a tecla pressionada por mais tempo. Para evitar receber várias entradas pressionadas, use o loop while e passe-o.
fonte
se você quiser apenas segurar a tela para ver o resultado no terminal, basta escrever
no final do código e ele manterá a tela
fonte
O build_input_input deve ajudar.
fonte