Réagir à la frappe d'une touche clavier pour un script en mode console
11 réponses
Francois Lafont
Bonjour à tous,
J'ai un petit programme en mode *console* qui simule une expérience
aléatoire un grand nombre de fois. Le programme fonctionne, mais il peut
mettre un peu de temps (10 minutes) à se terminer car il répète par
exemple 100 000 fois une même simulation. En gros, code, c'est ça :
for k in range(10000):
simule_experience()
affiche_petit_bilan()
J'aimerais que le programme réagisse quand j'appuie sur la barre espace.
Je m'explique.
Je lance le programme, il boucle, il boucle... je n'ai pas de prompt sur
la console pendant ce temps bien sûr. Si jamais j'appuie sur SPACE (et
seulement si je fais cela), dès que le programme arrive en début de
boucle, au lieu de simuler une nouvelle expérience, le programme se
stoppe et m'affiche un truc du genre «Pour l'instant 56 257 expériences
simulées, tapez ENTER pour que le programme reprenne son travail... ».
Dans ce cas, si j'appuie sur ENTER (et seulement si je fais cela), le
programme reprend ses boucles. Et ainsi de suite...
Merci beaucoup Pierre pour votre code, qui, pour l'avoir testé, fait exactement ce que j'ai demandé. Il ne me reste plus qu'à l'étudier (en l'état je suis loin de le maîtriser).
Le code de Pierre fait effectivement ce qu'il faut faire. J'ai juste une remarque sur l'utilisation à mon avis superflue de eval(). Il vaut peut-être mieux utiliser :
if os.name == 'posix': [...] fonction = lambda : sys.stdin.read(1) # ou simplement def fonction(): return sys.stdin.read(1) else: [...] fonction = msvcrt.getch
et plus bas utiliser fonction comme un "callable" normal
c = fonction()
Pour la partie termios, bonne lecture du man :-)
Je suis entièrement de votre avis. Ce qui s'est passé, c'est que dans l'excitation du moment j'avais d'abord pensé à l'approche fonctionnelle et été perturbé par le fait qu'une fonction prenait 0 paramètres et l'autre 1 (constant). D'où l'eval sans enthousiasme. Ce qui est très con puisque j'utilise massivement les lambda de cette façon dans des dictionnaires d'actions. Alors j'ai repris le code dans l'idée d'en archiver une version nettoyée, entre autre de l'eval. On peut également conditionner tout le /def kbThreah(): etc./. Et j'ai regardé le code de la branche posix, que j'avais lamentablement pompé sur la toile. Ça ne m'a pas trop plu, quand j'ai constaté qu'on bouclait sans fin sur une exception. Je ne connais rien de la gestion des priorités des threads Python, je me suis dit qu'enfiler un sleep() à ce niveau devrait améliorer les choses
while c != ' ': try: c = sys.stdin.read(1) except IOError: time.sleep(0.1)
et puis je suis parti sur d'autres recherches sur des entrées clavier bloquantes peu gourmandes, mais je n'ai rien trouvé d'enthousiasmant.
Merci beaucoup Pierre pour votre code, qui, pour l'avoir testé, fait
exactement ce que j'ai demandé. Il ne me reste plus qu'à l'étudier (en
l'état je suis loin de le maîtriser).
Le code de Pierre fait effectivement ce qu'il faut faire. J'ai juste une
remarque sur l'utilisation à mon avis superflue de eval(). Il vaut
peut-être mieux utiliser :
if os.name == 'posix':
[...]
fonction = lambda : sys.stdin.read(1)
# ou simplement def fonction(): return sys.stdin.read(1)
else:
[...]
fonction = msvcrt.getch
et plus bas utiliser fonction comme un "callable" normal
c = fonction()
Pour la partie termios, bonne lecture du man :-)
Je suis entièrement de votre avis. Ce qui s'est passé, c'est que dans
l'excitation du moment j'avais d'abord pensé à l'approche fonctionnelle
et été perturbé par le fait qu'une fonction prenait 0 paramètres et
l'autre 1 (constant). D'où l'eval sans enthousiasme. Ce qui est très
con puisque j'utilise massivement les lambda de cette façon dans des
dictionnaires d'actions.
Alors j'ai repris le code dans l'idée d'en archiver une version
nettoyée, entre autre de l'eval. On peut également conditionner tout le
/def kbThreah(): etc./.
Et j'ai regardé le code de la branche posix, que j'avais lamentablement
pompé sur la toile. Ça ne m'a pas trop plu, quand j'ai constaté qu'on
bouclait sans fin sur une exception. Je ne connais rien de la gestion
des priorités des threads Python, je me suis dit qu'enfiler un sleep()
à ce niveau devrait améliorer les choses
while c != ' ':
try:
c = sys.stdin.read(1)
except IOError:
time.sleep(0.1)
et puis je suis parti sur d'autres recherches sur des entrées clavier
bloquantes peu gourmandes, mais je n'ai rien trouvé d'enthousiasmant.
Merci beaucoup Pierre pour votre code, qui, pour l'avoir testé, fait exactement ce que j'ai demandé. Il ne me reste plus qu'à l'étudier (en l'état je suis loin de le maîtriser).
Le code de Pierre fait effectivement ce qu'il faut faire. J'ai juste une remarque sur l'utilisation à mon avis superflue de eval(). Il vaut peut-être mieux utiliser :
if os.name == 'posix': [...] fonction = lambda : sys.stdin.read(1) # ou simplement def fonction(): return sys.stdin.read(1) else: [...] fonction = msvcrt.getch
et plus bas utiliser fonction comme un "callable" normal
c = fonction()
Pour la partie termios, bonne lecture du man :-)
Je suis entièrement de votre avis. Ce qui s'est passé, c'est que dans l'excitation du moment j'avais d'abord pensé à l'approche fonctionnelle et été perturbé par le fait qu'une fonction prenait 0 paramètres et l'autre 1 (constant). D'où l'eval sans enthousiasme. Ce qui est très con puisque j'utilise massivement les lambda de cette façon dans des dictionnaires d'actions. Alors j'ai repris le code dans l'idée d'en archiver une version nettoyée, entre autre de l'eval. On peut également conditionner tout le /def kbThreah(): etc./. Et j'ai regardé le code de la branche posix, que j'avais lamentablement pompé sur la toile. Ça ne m'a pas trop plu, quand j'ai constaté qu'on bouclait sans fin sur une exception. Je ne connais rien de la gestion des priorités des threads Python, je me suis dit qu'enfiler un sleep() à ce niveau devrait améliorer les choses
while c != ' ': try: c = sys.stdin.read(1) except IOError: time.sleep(0.1)
et puis je suis parti sur d'autres recherches sur des entrées clavier bloquantes peu gourmandes, mais je n'ai rien trouvé d'enthousiasmant.