我有一個函數foo,隻有在滿足條件後才會停止。 當foo正在運作時,我需要一直詢問使用者輸入(不斷詢問使用者輸入)。 我希望它們分開運作而不會互相幹擾。
在下面的示例中,foo繼續列印"Hello",getUserInput一直在尋找使用者輸入。 即使我沒有為使用者輸入輸入任何内容,我也希望foo繼續列印你好。 隻要使用者沒有輸入字母'e',它就會一直詢問輸入。 我有以下嘗試:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28import threading
from time import sleep
class test:
def __init__(self):
self.running = True
def foo(self):
while(self.running):
print 'Hello
'
sleep(2)
def getUserInput(self):
x = ''
while(x != 'e'):
x = raw_input('Enter value: ')
self.running = False
def go(self):
th1 = threading.Thread(target=self.foo)
th2 = threading.Thread(target=self.getUserInput)
th1.start()
th2.start()
t = test()
t.go()
我的代碼列印出第一個問候語并要求輸入,但之後沒有任何内容。 我究竟做錯了什麼? 感謝您的幫助。
對我來說很好。
如果你根本不輸入任何東西,它還能繼續列印你好嗎?
是的,每2秒一次。
你在運作哪個版本的python?
OSX 10.6.8上的2.6.1。 也适用于2.5.4和2.7.2。
那對我來說這對我來說很奇怪。 我在Windows 7上有32位python,2.7.2(64位,我的一些子產品與64位不相容,是以32位python)。 謝謝你順便提一下。
在python 2.7.2 FreeBSD amd64(64位)上運作正常。
我在另一台機器上運作它,我遇到了同樣的問題。 也許我沒有正确澄清我的目标/目标。 我希望兩個線程彼此獨立運作,無論輸入是否輸入,你每2秒列印一次hello。 目前,除非我輸入一些輸入,否則它不會列印下一個問候語。
更新:開啟者在IDLE上的Windows上運作他的代碼。關于I / O,它的行為與shell或Windows指令行不同。他的代碼适用于Windows指令行。
原則上,您的代碼适合我。我正在運作Python 2.6.5。
這裡有幾條評論:
1)在你的情況下,隻有兩個線程是好的:主線程和另一個線程。但是,它也可以使用三個。隻是你的主線程隻是等待其他線程完成。
2)你應該明确地join()你産生的所有線程。您在終止它之前在主線程中執行此操作。記錄您生成的線程(例如在清單threads中),然後在程式結束時加入它們(例如for t in threads: t.join())。
3)您線上程之間共享變量self.running。在這種情況下它很好,因為一個線程隻讀取它而另一個隻寫它。通常,您需要非常小心共享變量并在更改之前擷取鎖定。
4)你應該在主線程中捕獲KeyboardInterrupt異常并找到一種方法與你的其他線程進行通信以終止:)
5)使用小寫方法名稱,是以代替getUserInput将其命名為get_user_input。使用大寫的類名并從object繼承:class Test(object):
這是一個運作的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60import threading
from time import sleep
def main():
t = Test()
t.go()
try:
join_threads(t.threads)
except KeyboardInterrupt:
print"
KeyboardInterrupt catched."
print"Terminate main thread."
print"If only daemonic threads are left, terminate whole program."
class Test(object):
def __init__(self):
self.running = True
self.threads = []
def foo(self):
while(self.running):
print '
Hello
'
sleep(2)
def get_user_input(self):
while True:
x = raw_input("Enter 'e' for exit:")
if x.lower() == 'e':
self.running = False
break
def go(self):
t1 = threading.Thread(target=self.foo)
t2 = threading.Thread(target=self.get_user_input)
# Make threads daemonic, i.e. terminate them when main thread
# terminates. From: http://stackoverflow.com/a/3788243/145400
t1.daemon = True
t2.daemon = True
t1.start()
t2.start()
self.threads.append(t1)
self.threads.append(t2)
def join_threads(threads):
"""
Join threads in interruptable fashion.
From http://stackoverflow.com/a/9790882/145400
"""
for t in threads:
while t.isAlive():
t.join(5)
if __name__ =="__main__":
main()
鍵入e或E時,程式會在短暫延遲後結束(按照您的意圖)。按ctrl + c時,它會立即終止。制作一個使用threading響應異常的程式比預期的要複雜一些。我在上面的源代碼中包含了重要的參考資料。
這是它在運作時的樣子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15$ python supertest.py
Hello
Enter 'e' for exit:
Hello
Hello
Hello
e
$
謝謝,我一定會記住這一切。
非常感謝。我非常感謝你的努力。我現在使用的是Python 3.2.3,即使使用你的代碼,我仍然會遇到相同的行為。你好列印一次,然後控制台隻是等待我的輸入而沒有任何連續列印你好。有什麼想法嗎?
你可以在你的系統上執行Python 2.7上的代碼嗎?
我将再次編輯答案,并向您展示輸出的樣子。編輯:完成。
是的我在2.7以及2個不同硬體上的Python 3上嘗試過它。
你如何調用該腳本?從Windows指令行或您是否使用IDLE?
我正在與IDLE合作。一旦我輸入一些輸入,即使在32位Windows XP上,它也隻列印下一個問候
IDLE是一個非常特殊的環境。它是為了發展,而不是為了生産。請從windows指令行運作代碼:c:\path\to\python.exe test.py
IDLE可能在等待輸入時阻塞輸出。是以你的線程可能正在嘗試列印你好,但空閑不會讓它直到輸入得到解決。是的,在指令行中運作它
這是令人尴尬的,是的,現在确實有效。非常感謝。我要確定從現在開始從指令行運作所有内容。我還在學習python :)
@AasamTasaddaq,這很好。它是IDLE的一個實作細節,你不應該因為不知道這一點而受到責備。我覺得你在解決這個問題的過程中學到了很多東西:)
這是非常正确的,我很高興我遇到了這個問題。
并且不要忘記考慮接受答案;)晚安!