2009-02-11 7 views
0

Peut-être que je ne peux pas faire ce que je veux? Je veux avoir 1 thread faire w/e il veut et un 2ème thread à l'entrée de l'utilisateur recv pour définir le drapeau de quitter. en utilisant ce code je veux entrer q pour quitter à tout moment ou avoir l'impression hey délai d'attente après 6 foispython, affaire amusante avec des threads et des IDEs?

import sys 
import threading 
import time 

class MyThread (threading.Thread): 
    def run (s): 
     try: 
      s.wantQuit = 0 
      while(not s.wantQuit): 
       print "want input" 
       button = raw_input() 
       if button == "q": 
        s.wantQuit=1 
     except KeyboardInterrupt: 
      s.wantQuit = 1 
      print "abort with KeyboardInterrupt" 
     print "done mythread" 

myThread = MyThread() 
myThread.start() 

a=5 
while not myThread.wantQuit: 
    print "hey" 
    if (a == 0): 
     break; 
    a = a-1; 
    time.sleep(1) 
myThread.wantQuit=1 
print "main thread done" 

ce qui se passe est au lieu de deux fils que j'ai la principale impression hey 4/6 fois, puis une boîte de dialogue Poping jusqu'à demander mon entrée et l'application étant bloquée jusqu'à ce que je l'entre. WTF ?!

want input 
hey 
hey 
hey 
hey 
abort with KeyboardInterrupt 
done mythread 
main thread done 

J'utilise PyScripter (il a le débogage), j'ai aussi essayé pydle qui ne marche pas semble me permettre d'entrer dans l'entrée et se bloque finalement après l'exécution d'une fois.

+0

Tout d'abord, utilisez "self" et non "s". Les programmeurs Python seront totalement confus si vous n'utilisez pas "self". – llimllib

+0

seconde, supprimer les parenthèses dans "while (pas self.wantQuit):", ils sont inutiles. – llimllib

+0

Troisièmement, je ne pense pas que raw_input fonctionne comme vous le pensez, vous devez appuyer sur "q " pour quitter, et pas seulement sur "q" – llimllib

Répondre

2

Le problème ici est que raw_input attend une entrée pour vider le flux d'entrée; consultez son documentation. PyScripter voit probablement que le programme attend une entrée et vous donne une boîte de saisie (je ne sais pas avec certitude, je ne l'ai jamais utilisé.)

Le programme fonctionne exactement comme je le souhaite depuis la ligne de commande; le thread secondaire bloque sur le raw_input jusqu'à ce que j'appuie sur "q [enter]", à quel point le programme se termine.

Ce n'est pas, AFAICS, facile à vérifier et de voir si un caractère est disponible dans le flux d'entrée avant de bloquer sur un appel en lecture. Vous devriez probablement vérifier this thread sur la façon de lire un personnage d'une manière bloquante sans avoir besoin d'un [enter], puis this post sur le défi de lire un personnage sans le bloquer du tout.

Vous pouvez éventuellement utiliser une combinaison de msvcrt.kbhit sur Windows et this recipe à partir de la FAQ python pour obtenir le caractère q sans avoir besoin d'une pression sur une touche, mais je vais le laisser comme un exercice pour le lecteur.

Addendum: Une chose que vous pourriez faire serait d'utiliser la bibliothèque de sélection pour définir un délai d'attente sur lit à partir du clavier, ce qui rendra votre acte de programme plus comme vous attendez:

import sys 
import threading 
import time 
import select 

def timeout_read(n_chars): 
    r, _, _ = select.select([sys.stdin], [], [], 1) 
    return r[0].read(n_chars) if r else "" 

class MyThread (threading.Thread): 
    def run (self): 
     try: 
      self.wantQuit = 0 
      while not self.wantQuit: 
       print "want input" 
       button = timeout_read(1) 
       if button == "q": 
        self.wantQuit=1 
     except KeyboardInterrupt: 
      self.wantQuit = 1 
      print "abort with KeyboardInterrupt" 
     print "done mythread" 

myThread = MyThread() 
myThread.start() 

a=5 
while not myThread.wantQuit: 
    print "hey" 
    if (a == 0): 
     break; 
    a = a-1; 
    time.sleep(1) 
myThread.wantQuit=1 
print "main thread done" 

Notez que vous toujours besoin d'appuyer sur "q [enter]" avec cette solution.

Questions connexes