Existe-t-il un moyen de lire un seul caractère de l'entrée utilisateur? Par exemple, ils appuient sur une touche du terminal et celle-ci est retournée (un peu comme getch()
). Je sais qu'il y a une fonction dans Windows pour cela, mais j'aimerais quelque chose qui soit multiplateforme.
262
msvcrt.getch
parmsvcrt.getwch
, comme suggéré ici.Réponses:
Voici un lien vers un site qui explique comment lire un seul caractère sous Windows, Linux et OSX: http://code.activestate.com/recipes/134892/
la source
ImportError
exception est utilisée comme une sorte de déclaration if; pourquoi ne pas appeler platform.system () pour vérifier le système d'exploitation?va essentiellement lire 1 octet de STDIN.
Si vous devez utiliser la méthode qui n'attend pas le,
\n
vous pouvez utiliser ce code comme suggéré dans la réponse précédente:( extrait de http://code.activestate.com/recipes/134892/ )
la source
La recette ActiveState citée textuellement dans deux réponses est sur-conçue. Cela peut se résumer à ceci:
la source
0
.La bibliothèque readchar , également basée sur la recette ActiveState mentionnée dans d'autres réponses, mérite également d'être essayée .
Installation:
Usage:
Testé sur Windows et Linux avec Python 2.7.
Sous Windows, seules les clés qui tracent des lettres ou des codes de contrôle ASCII sont pris en charge ( Backspace, Enter, Esc, Tab, Ctrl+ lettre ). Sur GNU / Linux ( en fonction de la borne exacte, peut-être?) , Vous obtenez également Insert, Delete, Pg Up, Pg Dn, Home, Endet les clés ... mais, il y a des problèmes qui séparent ces touches spéciales d'un .F nEsc
Mise en garde: comme avec la plupart (toutes?) Des réponses ici, les touches de signal comme Ctrl+ C, Ctrl+ Det Ctrl+ Zsont capturées et retournées (comme
'\x03'
,'\x04'
et'\x1a'
respectivement); votre programme peut être difficile à abandonner.la source
Une méthode alternative:
De ce billet de blog .
la source
| os.O_NONBLOCK
. Sinon, vous pouvez le mettre en boucle (bonne idée de dormir un peu dans la boucle pour éviter de tourner).while True
alorswhile 1
.Ce code, basé ici , augmentera correctement KeyboardInterrupt et EOFError si vous appuyez sur Ctrl+ Cou Ctrl+ D.
Devrait fonctionner sous Windows et Linux. Une version OS X est disponible à partir de la source d'origine.
la source
La réponse (actuellement) la mieux classée (avec le code ActiveState) est trop compliquée. Je ne vois pas de raison d'utiliser des classes alors qu'une simple fonction devrait suffire. Voici deux implémentations qui accomplissent la même chose mais avec un code plus lisible.
Ces deux implémentations:
Version 1: lisible et simple
Version 2: évitez les importations répétées et la gestion des exceptions:
[EDIT] J'ai raté un avantage du code ActiveState. Si vous prévoyez de lire des caractères plusieurs fois, ce code évite le coût (négligeable) de la répétition de l'importation Windows et de la gestion des exceptions ImportError sur les systèmes de type Unix. Alors que vous devriez probablement être plus préoccupé par la lisibilité du code que par cette optimisation négligeable, voici une alternative (elle est similaire à la réponse de Louis, mais getChar () est autonome) qui fonctionne de la même manière que le code ActiveState et est plus lisible:
Exemple de code qui exerce l'une des versions de getChar () ci-dessus:
la source
Cela peut être un cas d'utilisation pour un gestionnaire de contexte. Laissant de côté les allocations pour Windows OS, voici ma suggestion:
la source
self
en__enter__
et uneread
méthode qui retournesys.stdin.read(1)
, alors vous pouvez lire plusieurs caractères dans un contexte.Essayez d'utiliser ceci: http://home.wlu.edu/~levys/software/kbhit.py C'est non bloquant (cela signifie que vous pouvez avoir une boucle while et détecter une pression de touche sans l'arrêter) et multiplateforme.
Un exemple pour utiliser ceci:
Ou vous pouvez utiliser le module getch de PyPi . Mais cela bloquerait la boucle while
la source
Ceci est NON BLOCANT, lit une clé et la stocke dans keypress.key.
dans votre programme
la source
Les réponses ici étaient informatives, mais je voulais également un moyen d'obtenir des pressions de touches de manière asynchrone et de déclencher des pressions de touches dans des événements distincts, le tout de manière thread-safe et multiplateforme. PyGame était également trop gonflé pour moi. J'ai donc fait ce qui suit (en Python 2.7 mais je pense qu'il est facilement portable), que j'ai pensé partager ici au cas où cela serait utile pour quelqu'un d'autre. J'ai stocké cela dans un fichier nommé keyPress.py.
L'idée est que vous pouvez simplement appeler
keyPress.getKey()
, qui lira une touche du clavier, puis la renverra.Si vous voulez quelque chose de plus que ça, j'ai fait un
KeyCapture
objet. Vous pouvez en créer un via quelque chose commekeys = keyPress.KeyCapture()
.Ensuite, vous pouvez faire trois choses:
addEvent(functionName)
prend n'importe quelle fonction qui prend un paramètre. Ensuite, chaque fois qu'une touche est enfoncée, cette fonction sera appelée avec la chaîne de cette touche en entrée. Ceux-ci sont exécutés dans un thread séparé, vous pouvez donc bloquer tout ce que vous voulez et cela ne gâchera pas les fonctionnalités de KeyCapturer et ne retardera pas les autres événements.get()
renvoie une clé de la même manière que précédemment. Il est maintenant nécessaire ici car les clés sont capturées via l'KeyCapture
objet maintenant, donckeyPress.getKey()
serait en conflit avec ce comportement et les deux manqueraient certaines clés car une seule clé peut être capturée à la fois. Supposons également que l'utilisateur appuie sur «a», puis sur «b», vous appelezget()
, l'utilisateur appuie sur «c». Cetget()
appel renverra immédiatement «a», puis si vous l'appelez à nouveau, il renverra «b», puis «c». Si vous l'appelez à nouveau, il se bloquera jusqu'à ce qu'une autre touche soit enfoncée. Cela garantit que vous ne manquez aucune clé, de manière bloquante si vous le souhaitez. Donc, de cette façon, c'est un peu différentkeyPress.getKey()
d'avantSi vous voulez que le comportement de
getKey()
retour,get(lossy=True)
c'est commeget()
, sauf qu'il ne renvoie que les touches enfoncées après l'appel àget()
. Ainsi, dans l'exemple ci-dessus,get()
bloquerait jusqu'à ce que l'utilisateur appuie sur «c», puis si vous l'appelez à nouveau, il se bloquerait jusqu'à ce qu'une autre touche soit enfoncée.getAsync()
est un peu différent. Il est conçu pour quelque chose qui fait beaucoup de traitement, puis revient parfois et vérifie quelles touches ont été enfoncées.getAsync()
Retourne ainsi une liste de toutes les touches enfoncées depuis le dernier appel àgetAsync()
, dans l'ordre de la touche la plus ancienne à la touche la plus récente. Il ne bloque pas non plus, ce qui signifie que si aucune touche n'a été enfoncée depuis le dernier appel àgetAsync()
, un espace vide[]
sera retourné.Pour commencer à capturer les clés, vous devez appeler
keys.startCapture()
avec votrekeys
objet ci-dessus.startCapture
n'est pas bloquant et démarre simplement un thread qui enregistre simplement les pressions de touches et un autre thread pour traiter ces pressions de touches. Il existe deux threads pour garantir que le thread qui enregistre les pressions de touches ne manque aucune touche.Si vous voulez arrêter la capture des clés, vous pouvez appeler
keys.stopCapture()
et cela arrêtera la capture des clés. Cependant, étant donné que la capture d'une clé est une opération de blocage, les clés de capture de thread peuvent capturer une clé de plus après l'appelstopCapture()
.Pour éviter cela, vous pouvez passer un ou plusieurs paramètres facultatifs dans
startCapture(functionName, args)
une fonction qui fait juste quelque chose comme vérifier si une clé est égale à «c», puis se ferme. Il est important que cette fonction fasse très peu avant, par exemple, un sommeil ici nous fera manquer des touches.Cependant, si
stopCapture()
est appelé dans cette fonction, les captures de touches seront arrêtées immédiatement, sans essayer d'en capturer plus, et que tous lesget()
appels seront renvoyés immédiatement, avec Aucun si aucune touche n'a encore été enfoncée.De plus, puisque
get()
etgetAsync()
mémorisez toutes les touches précédentes enfoncées (jusqu'à ce que vous les récupériez), vous pouvez appelerclearGetList()
etclearAsyncList()
oublier les touches précédemment enfoncées.Notez que
get()
,getAsync()
et les événements sont indépendants, donc si une touche est enfoncée: 1. Un appel àget()
celui en attente, avec perte activée, renverra cette touche. Les autres appels en attente (le cas échéant) continueront à attendre. 2. Cette clé sera stockée dans la file d'attente des clés get, de sorte qu'en casget()
de perte désactivée, la clé la plus ancienne appuyée ne soit pas encore retournéeget()
. 3. Tous les événements seront déclenchés avec cette clé comme entrée. 4. Cette clé sera stockée dans la liste desgetAsync()
clés, où cette liste sera retournée et définie sur une liste vide lors du prochain appel àgetAsync()
Si tout cela est trop, voici un exemple d'utilisation:
Cela fonctionne bien pour moi d'après le test simple que j'ai fait, mais je serai ravi de prendre également en compte les commentaires des autres s'il y a quelque chose qui m'a manqué.
Je l'ai également posté ici .
la source
Un commentaire dans l'une des autres réponses mentionne le mode cbreak, qui est important pour les implémentations Unix car vous ne voulez généralement pas que ^ C (
KeyboardError
) soit consommé par getchar (comme il le fera lorsque vous définissez le terminal en mode brut, comme cela est fait par la plupart des autres réponses).Un autre détail important est que si vous cherchez à lire un caractère et non un octet , vous devez lire 4 octets dans le flux d'entrée, car c'est le nombre maximal d'octets qu'un seul caractère comprendra en UTF-8 (Python 3+ ). La lecture d'un seul octet produira des résultats inattendus pour les caractères multi-octets tels que les flèches du clavier.
Voici mon implémentation modifiée pour Unix:
la source
Essayez ceci avec pygame:
la source
pygame.error: video system not initialized
La recette de l'ActiveState semble contenir un petit bug pour les systèmes "posix" qui empêche l'
Ctrl-C
interruption (j'utilise Mac). Si je mets le code suivant dans mon script:Je ne pourrai jamais terminer le script avec
Ctrl-C
, et je dois tuer mon terminal pour m'échapper.Je crois que la ligne suivante en est la cause, et c'est aussi trop brutal:
Mis à part cela, le package
tty
n'est pas vraiment nécessaire, iltermios
suffit de le gérer.Ci-dessous est le code amélioré qui fonctionne pour moi (
Ctrl-C
interrompra), avec lagetche
fonction supplémentaire qui fait écho au caractère pendant que vous tapez:Références:
la source
Le
curses
package en python peut être utilisé pour entrer en mode "brut" pour la saisie de caractères depuis le terminal avec seulement quelques instructions. L'utilisation principale de Curses est de reprendre l'écran pour la sortie, ce qui peut ne pas être ce que vous voulez. Cet extrait de code utilise desprint()
instructions à la place, qui sont utilisables, mais vous devez savoir comment les curses modifient les fins de ligne attachées à la sortie.la source
Si je fais quelque chose de compliqué, j'utiliserai des malédictions pour lire les clés. Mais souvent, je veux juste un simple script Python 3 qui utilise la bibliothèque standard et puisse lire les touches fléchées, alors je fais ceci:
la source
Ma solution pour python3, ne dépendant d'aucun paquet pip.
la source
Je pense que c'est l'une des solutions les plus élégantes.
puis utilisez-le dans le code:
la source
La réponse acceptée n'a pas très bien fonctionné pour moi (je détiendrais une touche, rien ne se passerait, puis j'appuierais sur une autre touche et cela fonctionnerait).
Après avoir appris le module curses , cela semble vraiment être la bonne voie à suivre. Et il est désormais disponible pour Windows via des curseurs Windows (disponibles via pip), vous pouvez donc programmer de manière indépendante de la plate-forme. Voici un exemple inspiré de ce joli tutoriel sur YouTube:
Enregistrez-le avec une
.py
extension ou exécutez-lecurses.wrapper(getkey)
en mode interactif.la source
Répondu ici: raw_input en python sans appuyer sur Entrée
Utilisez ce code-
Référence: https://github.com/unfor19/mg-tools/blob/master/mgtools/get_key_pressed.py
la source
Si vous ne souhaitez enregistrer qu'une seule touche, appuyez sur, même si l'utilisateur l'a appuyée plusieurs fois ou a continué d'appuyer sur la touche plus longtemps. Pour éviter d'obtenir plusieurs entrées pressées, utilisez la boucle while et passez-la.
la source
si vous voulez simplement maintenir l'écran afin que vous puissiez voir le résultat sur le terminal, il suffit d'écrire
à la fin du code et il tiendra l'écran
la source
Le raw_input intégré devrait aider.
la source