python threading
- pythonを使ったマルチスレッド処理の実装。
- 複数の処理を並列処理として記述することができる。
シンプルな例
- 2つの関数を並列で実行
ソースコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env python
import threading
import time
def thread1():
print "thread1: start"
time.sleep(2)
print "thread1: end"
def thread2():
print "thread2: start"
time.sleep(1)
print "thread2: end"
if __name__ == '__main__':
t1 = threading.Thread(target=thread1)
t2 = threading.Thread(target=thread2)
t1.start()
t2.start()
- thread1とthread2を順に起動。
- シーケンシャルでれば、thread1終了後thread2が実行されるが、マルチスレッドなので、同時に実行される。
- thread2はthread1よりも後に起動したが、sleep時間がthread1よりも短いため、早く終了する。
ループ処理
- 2つの無限ループをマルチスレッドで実装する。
- ctrl+C が押された際に、すべての処理を終了する。
ソースコード
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
#!/usr/bin/env python
import threading
import time
import signal
class ThreadingTest:
def __init__(self):
self.exit_signal = False
signal.signal(signal.SIGINT, self.Handler)
self.t1 = threading.Thread(target=self.thread1)
self.t2 = threading.Thread(target=self.thread2)
self.t1.setDaemon(True)
self.t2.setDaemon(True)
def Run(self):
self.t1.start()
self.t2.start()
while not self.exit_signal:
time.sleep(1)
def Handler(self, signal, frame):
self.exit_signal = True
def thread1(self):
while(True):
print "thread1: working"
time.sleep(1)
def thread2(self):
while(True):
print "thread2: working"
time.sleep(2)
if __name__ == '__main__':
threading_test = ThreadingTest()
threading_test.Run()
- メインスレッドでsignalのハンドラを設定しておく。
- ctrl+cが押されたら、メインスレッドの処理を終了する。
- thread1とthread2はデーモンに設定しておくことで。メインスレッドが終了すると自動的に終了する。
- signalのハンドラはメインスレッドでしか動作しないので注意(メインスレッドを終了するとctrl+cが効かなくなる)。
Opencvでのマルチスレッド処理
- python-opencvでカメラ画像を取得して画像処理を施し、表示する処理をマルチスレッドによって実装
- サンプルとしてカメラ画像をグレースケール化して表示する処理を実装
- ctrl+cまたはqが押されたらすべての処理を終了
ソースコード
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
60
61
62
63
#!/usr/bin/env python
import threading
import time
import cv2
import numpy as np
import signal
class OpencvThreading:
def __init__(self):
self.exit_signal = False
signal.signal(signal.SIGINT, self.Handler)
self.cap = cv2.VideoCapture(0)
if not self.cap.isOpened():
print "error: cannot open camera"
sys.exit()
self.process_rate = 10.0 # 10 Hz
self.update_rate = 60.0 # 60 Hz
self.update = threading.Thread(target=self.UpdateFrame)
self.proc = threading.Thread(target=self.Processing)
self.proc.setDaemon(True)
def MouseCB(self, eventType, x, y, flags, userdata):
if eventType == cv2.EVENT_LBUTTONDOWN:
print "click"
def UpdateFrame(self):
self.frame = self.out = np.zeros((1,1,3), np.uint8)
cv2.namedWindow("window", cv2.WINDOW_AUTOSIZE)
cv2.imshow("window", self.out)
cv2.setMouseCallback("window", self.MouseCB, None)
while(True):
ret, self.frame = self.cap.read()
if not ret:
print "error: cannot get frame"
break
cv2.imshow("window", self.out)
key = cv2.waitKey(int(1000.0 * 1.0 / self.update_rate))
if key & 0xFF == ord('q') or self.exit_signal:
break
def Processing(self):
while(True):
self.out = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
time.sleep(1.0 / self.process_rate)
def Run(self):
self.update.start()
self.proc.start()
while(True):
self.update.join(1)
if not self.update.is_alive():
break
def Handler(self, signal, frame):
self.exit_signal = True
if __name__ == '__main__':
opencv_threading = OpencvThreading()
opencv_threading.Run()
- スレッドを2つ(画像の読み込みと表示、グレースケール化)用意
- グレースケール化処理は、デーモンにすることで、他の処理が終了したら、同時に終了するように設定
- 画像の読み込みと表示は、デーモンにせず、waitKeyでqが押されるまたは、ctrl+cが押されたらbreakするように設定
- メインスレッド(スレッド処理の外)では、is_alive()を使って、画像の更新と読み込みのスレッドが終了しているか監視し、終了していたら、プログラムを終了する。
reference
- [Python] スレッドで実装する, Qiita
- threading, Python The Standard Library
- signal, Python The Standard Library
- OpenCV 接続したカメラから動画を取得しよう (Python), WEB ARCH LABO
TOP | back |