简体   繁体   中英

python, funny business with threads and IDEs?

Maybe i cant do what i want? I want to have 1 thread do w/e it wants and a 2nd thread to recv user input to set the quit flag. using this code i want to enter q anytime to quit or have it timeout after printing hey 6 times

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"

what happens is instead of two threads i have the main one printing hey 4/6 times, then a dialog poping up asking for my input and the app being locked up until i enter it. WTF?!

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

i am using PyScripter (it has debugging), i also tried pydle which doesnt seem to allow me to enter input and locks up eventually after running it once.

The problem here is that raw_input waits for an enter to flush the input stream; check out its documentation . PyScripter is probably seeing that the program is waiting for an input and giving you an input box (don't know for sure, never used it.)

The program works exactly as I expect it to from the command line; the secondary thread blocks on the raw_input until I hit "q[enter]", at which point the program ends.

It is not, AFAICS, easy to check and see if a character is available in the input stream before blocking on a read call. You probably should check out this thread on how to read a character in a blocking fashion without requiring an [enter], and then this post on the challenge of reading a character without blocking at all.

You can possibly use a combination of msvcrt.kbhit on windows and this recipe from the python FAQ to get the q character without requiring a keypress, but I'll leave it as an exercise to the reader.

Addendum: One thing you could do would be to use the select library to set a timeout on reads from the keyboard, which will make your program act more like you expect:

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"

Note that you will still need to press "q[enter]" with this solution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM