콘솔워크

qthread를 이용한 프로그램에서 GUI 로그창에 메시지 남길 때 주의 점 본문

프로그래밍/python

qthread를 이용한 프로그램에서 GUI 로그창에 메시지 남길 때 주의 점

이휘재123 2022. 8. 17. 10:45
반응형
class WriterThread(QThread):

    def __init__(self, parent, excel_file):
        super().__init__(parent)
        self.parent = parent
        self.excel_file = excel_file

    def run(self):
        try:
            self.parent.log_append(f'작업 시작')
        except Exception as e:
            print(e)


    def stop(self):
        try:
            self.parent.log_append(f'작업 중지')
            self.terminate()
        except Exception as e:
            print(e)


class MainUI(QWidget):

    # 초기화
    def __init__(self):
        super().__init__()
        self.initUI()


    # 로그 작성
    def log_append(self, text):
        now = str(datetime.now())[0:-7]
        self.browser.append(f'[{now}] {text}')

    # 메인 UI
    def initUI(self):

        # 상단 좌측
        top_left_groupbox = QGroupBox('엑셀파일')
        top_left_inner_layout = QHBoxLayout
        top_left_groupbox.setLayout(top_left_inner_layout)

        # 상단 우측
        top_right_groupbox = QGroupBox('조작')
        top_right_inner_layout = QHBoxLayout()
        top_right_groupbox.setLayout(top_right_inner_layout)

        # 중단 (로그)
        center_groupbox = QGroupBox('로그')
        self.browser = QTextBrowser()

        center_inner_layout = QHBoxLayout()
        center_inner_layout.addWidget(self.browser)
        center_groupbox.setLayout(center_inner_layout)


        # 레이아웃 배치
        top_layout = QHBoxLayout()
        top_layout.addWidget(top_left_groupbox, 4)
        top_layout.addWidget(top_right_groupbox, 2)

        center_layout = QGridLayout()
        center_layout.addWidget(center_groupbox, 0, 0)


        layout = QGridLayout()
        layout.addLayout(top_layout, 0, 0)
        layout.addLayout(center_layout, 1, 0)

        self.setLayout(layout)


        # 앱 기본 설정
        self.setWindowTitle('auto writer')
        self.resize(1000, 800)
        self.center()
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MainUI()
    sys.exit(app.exec_())

해당 코드는 로그창이 존재하는 GUI이고 Qthread를 이용해서 메인코드를 작동 시키는 용도이다. (부분 생략)

 

WriterThread 클래스를 보면 슬롯을 이용하지 않고 부모의 log_append를 이용해 로그를 작성하는 모습을 볼 수 있는데, 이렇게 작성해도 작동을 하긴 하지만, Qthread상에서 메인스레드에 바로 접근을 하기 때문에 안정성이 떨어져 프로그램이 종료되는 경우가 있다.

 

 

때문에 아래와 같은 GUI처럼 QtCore를 이용해서 로그창에 접근하는 편이 안정성이 더 좋다. (GUI부분 코드 생략)

class SampleThread(QThread):

	# 슬롯
    log_msg = QtCore.pyqtSignal(str)

    def __init__(self, GUI, excel_file):
        super().__init__()
        self.GUI = GUI
        self.excel_file = excel_file

    def run(self):
        try:
            self.log_msg.emit(f"스레드 시작") # emit을 이용해 사용하는 모습
            self.log_msg.emit(f"{self.excel_file}")
            print(f"스레드 시작")
        except Exception as e:
            print(e)

    def stop(self):
        try:
            self.log_msg.emit(f"스레드 중지")
            self.terminate()
        except Exception as e:
            print(e)


class MainUI(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

	# 슬롯
    @pyqtSlot(str)
    def log_append(self, text):
        now = str(datetime.now())[0:-7]
        self.browser.append(f"[{now}] {text}")

    def button_clicked(self):
        # gui상에서는 log_append를 그대로 사용
        self.log_append(f"{self.excel_file_le.text()} 시작")

        #슬롯을 사용하는 부분
        self.sample = SampleThread(self, self.excel_file_le.text())
        self.sample.log_msg.connect(self.log_append) 
        self.sample.start()

 

반응형