본문 바로가기
프로그래밍 관련/PyQt

PyQt(4) 쓰레드 사용하기

by 존버매니아.임베디드 개발자 2021. 9. 14.
반응형

 

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QThread
import time
    
class MyThread(QThread):
    cnt=0

    def __init__(self):
        super().__init__()
   
    def run(self):
        
        while True:
            self.cnt=self.cnt+1
            print("running %d" %self.cnt)
            time.sleep(1)


class MyWindow(QMainWindow):
         
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Test")
        self.setGeometry(1000, 200, 300, 300)

        self.Thread1 = MyThread()
        self.Thread1.start()    


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()

    app.exec_()

 

Qthread를 상속받은 클래스를 정의하고,

Main Window 안에다가 해당 클래스를 사용한 객체를 만들어서 running 시켜주자.

 

위 코드를 실행하면 쓰레드 1개가 돌아가게 된다. 

 


쓰레드와 관련된 관찰기록

쓰레드 종료 구현하기

 

쓰레드를 사용자가 원하면 켜고, 필요없으면 끄고 하는 식으로 구현해보고 싶었는데

확실하진 않은데 일단 찾아본 바로는 파이썬의 쓰레드는 OS에서 Kill process 하는 것 마냥

쓰레드를 종료시켜버리는 것은 없는거 같다.

 

 

그래서 궁여지책으로 구성을 하면 다음과 같은데,

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QThread
import time
    
class MyThread(QThread):
    cnt=0

    def __init__(self):
        super().__init__()
        self.thr_run = True
    
    def thread_stop(self):
        self.thr_run = False

    def run(self):
        self.thr_run = True
        
        while self.thr_run == True:
            self.cnt=self.cnt+1
            print("running %d" %self.cnt)
            time.sleep(1)


class MyWindow(QMainWindow):
         
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyStock")
        self.setGeometry(1000, 200, 300, 300)

        # start 버튼 정의
        btnRun = QPushButton("Run", self)	# 버튼 텍스트
        btnRun.move(20, 20)	# 버튼 위치
        btnRun.clicked.connect(self.btn_clicked_1)	# 클릭 시 실행할

        # stop 버튼 정의
        btnRun2 = QPushButton("stop", self)	# 버튼 텍스트
        btnRun2.move(20, 80)	# 버튼 위치
        btnRun2.clicked.connect(self.btn_clicked_2)	# 클릭 시 실행할

        self.Thread1 = MyThread()
        

    def btn_clicked_1(self):
            self.Thread1.start()

    def btn_clicked_2(self):
            self.Thread1.thread_stop()

        


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()

    app.exec_()

 

위 예시코드에서

Start 버튼을 눌러서 Thread.start를 하면

쓰레드의 run 함수 안에 while 문이 돌아갈 것이다.

 

이 상태에서 Stop 버튼을 누르면

쓰레드 내의

self.thr_run 변수가 False가 되면서 while문을 빠져나가게 될 것이다.

 

그러면 이 쓰레드의 run 함수는 while문을 빠져나가면서 더 이상 실행할 코드가 없으므로 

함수콜해서 stack에 있다가 return 된 것 마냥 쓰레드가 종료될 것이라고 나는 생각했다.

 

근데 쓰레드가 종료되는 거였으면 객체를 반환했을 테니 

쓰레드 새로만들려면 다시 쓰레드 객체부터 새로만들어야되는데..뭐 그런 개념은 아니다.

 

다시 start를 하면 다시 run함수가 실행되는 구조다.


쓰레드 관련 이야기2

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QThread
import time
    
class MyThread(QThread):
    cnt=0

    def __init__(self):
        super().__init__()
        
    
    def thread_Other(self):
        for i in range(30):
            print("다른 함수 실행")
            time.sleep(1)

    def run(self):
        

        while True:
            self.cnt=self.cnt+1
            print("running %d" %self.cnt)
            time.sleep(1)


class MyWindow(QMainWindow):
         
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyStock")
        self.setGeometry(1000, 200, 300, 300)

        #버튼 정의
        btnRun = QPushButton("다른 메소드 실행", self)	# 버튼 텍스트
        btnRun.move(20, 20)	# 버튼 위치
        btnRun.clicked.connect(self.btn_clicked_1)	# 클릭 시 실행할     

        self.Thread1 = MyThread()
        self.Thread1.start()
     
    def btn_clicked_1(self):
            self.Thread1.thread_Other()
    


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myWindow = MyWindow()
    myWindow.show()

    app.exec_()

위 예시코드는

쓰레드 실행하면 run 함수안에 while문이 계속 돌아가는 와중에,

버튼을 누르면 큐쓰레드 객체 안에 other_fun 이라는 함수가 도중에 호출되서 실행되는 예제이다.

내가 처음에 잠깐 착각했던게

other_fun 함수는 큐 쓰레드 안에 있는 함수이기 때문에

other_fun 함수가 실행되는 동안에는 run 안에 while문이 pending 되어 안돌아가고 있을 거라고 생각했다.

근데 그건 내 오판이었다.

other_fun이 돌아가도 run은 쓰레드 이기 때문에 중간에 계속 계속 돌아가고 있다는 점을 유의할 필요가 있다.

running 1
running 2
다른 함수 실행
running 3
다른 함수 실행
running 4
다른 함수 실행
running 5
다른 함수 실행
running 6
다른 함수 실행
running 7

위는 실행결과를 찍은것인데,

다른 함수 실행이라는 other_fun안의 내용이 실행되는 와중에도 계속해서 run 함수가 돌아가고 있음을 볼 수 있다.

반응형