更新: オープナーは、IDLEのWindowsでコードを実行していました。I / Oに関しては、シェルやWindowsコマンドラインとは動作が異なります。彼のコードはWindowsコマンドラインで動作します。
原則として、あなたのコードは私のために働きます。Python2.6.5を実行しています。
ここにいくつかのコメント:
1)あなたの場合、メインスレッドともう1つのスレッドの2つのスレッドだけで十分です。ただし、3つでも機能します。メインスレッドは、他のスレッドが終了するのを待つ以外に何もしません。
join()
2)スポーンするすべてのスレッドを明示的に行う必要があります。これは、終了する前にメインスレッドで行います。生成したスレッドを記録し(たとえば、リストにthreads
)、プログラムの最後にそれらを結合します(たとえばfor t in threads: t.join()
)。
self.running
3)スレッド間で変数を共有します。この場合は、1つのスレッドがそれを読み取るだけで、別のスレッドがそれを書き込むだけなので、問題ありません。一般に、共有変数には十分注意し、変更する前にロックを取得する必要があります。
4)メインスレッドで例外をキャッチKeyboardInterrupt
し、他のスレッドと通信して終了する方法を見つける必要があります:)
getUserInput
5)小文字のメソッド名を使用するため、呼び出す代わりにget_user_input
。大文字のクラス名を使用し、以下から継承しobject
ます。class Test(object):
これは実行例です:
import threading
from time import sleep
def main():
t = Test()
t.go()
try:
join_threads(t.threads)
except KeyboardInterrupt:
print "\nKeyboardInterrupt 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 '\nHello\n'
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
、予想よりも少し注意が必要です。上記のソースに重要な参考資料を含めました。
実行時は次のようになります。
$ python supertest.py
Hello
Enter 'e' for exit:
Hello
Hello
Hello
e
$