※ 업무하면서 습득한 내용들을 정리해 놓은 포스팅입니다 :P 추가로 궁금하신 점은 댓글로 남겨주시고 필요한 자료 있으면 요청주세요! 잘못된 내용이 있으면 고쳐주시면 감사하겠습니다. 자료 퍼가실 때는 출처 남겨주세요!
ο 목차
※ 코드 보는 방법 참고
ㅇ 달러 기호($)가 있는 경우 -> 리눅스 터미널에서 CLI 명령어 입력
ㅇ "=#" 기호가 있는 경우 -> psql 쉘에서 명령어 입력
ㅇ 꺽쇠가 하나 있는 경우(>) -> 윈도우 명령 프롬프트(cmd)에서 명령어 입력
ㅇ 꺽쇠가 세개 있는 경우(>>>) -> python 쉘에서 명령어 입력
안녕하세요, 네모입니다.
pyqt5로 gui 코드 작성 중에 gui freezing 현상이 있어 문제 해결 방법을 공유하려고 합니다.
자세한 내용은 아래 사이트 참고 ↓↓↓↓
※ 참고 사이트 : https://realpython.com/python-pyqt-qthread/#freezing-a-gui-with-long-running-tasks
1. 문제 사례
gui 코드에서 Long-running task 실행시 gui 멈춤(gui freezing)* 현상 발생
* GUI freezing 현상이란?
- 위젯에서 장시간 처리가 필요한 함수(Long-runnint task)를 실행하는 경우 이벤트 루프가 그 함수를 처리하느라 위젯 상의 다른 인터랙션을 큐에만 차곡차곡 쌓아놓고 실제 처리를 못하게 되는 현상(gui freezing)
- 함수가 돌아가는 5분 동안 gui는 멈춘 것처럼 보이다가 그 함수가 끝난 후에야 인터렉션들을 순차적으로 처리하기 때문에 멈춘 것처럼 보여도 인터랙션들이 큐에 차곡차곡 쌓이기 때문에 프리징 상태에서 종료 버튼을 누른다면 프리징이 끝난 후 프로그램이 종료됩니다.
2. 문제 원인
메인 쓰레드의 자원을 Long-running task가 점유하여 task가 끝날 때까지 gui 이벤트 처리 불가
3. 해결 방법 개요
QThread를 사용하여 Long-running task를 메인 쓰레드와 분리된 별도의 쓰레드로 실행시킴(Long-running task offloading)
※ QThread 활용시 주의 사항 ↓↓
(1) Long-running task를 실행시키기 위한 모든 코드는 Long-running task 코드 안에 있어야 함
- 예시) lambda를 사용하는 경우 쓰레드 생성 불가 ↓↓ 아래 내용 참고
https://stackoverflow.com/questions/50596027/pyqt5-qthread-not-working-gui-still-freezing
(2) 사용자 지정 signal을 사용하는 경우(ex. finished) 인스턴스 어트리뷰트가 아닌 클래스 어트리뷰트(class attributes)로 생성
(3) GUI의 위젯은 thread-safe*가 아니기 때문에 thread 생성시 위젯과 관련된 요소들 배제
* thread-safe : 멀티 스레드 프로그래밍에서 일반적으로 어떤 함수나 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 의미함
- 예시) 아래는 제가 stackoverflow에 문의한 내용인데 혹시 참고하실 분들 있으면 참고하세요↓↓
https://stackoverflow.com/questions/73630171/pyqt5-gui-still-freezing-even-though-using-qthread
4. 문제 해결 방법
1) Thread 별도 생성을 위한 Thread 클래스(worker) 생성
from PyQt5 import QtCore
# QThread를 상속하는 Thread 클래스 생성
class Thread(QtCore.QThread):
# 쓰레드 종료시 종료 signal 생성을 위한 사용자 지정 시그널 객체 생성
finished = QtCore.pyqtSignal()
# Long-running task 함수 생성 부분
def LongRunningTask(self):
sleep(10)
# Thread 시작시 수행할 동작 지정
def run(self):
# Long-running task 실행
self.LongRunningTask()
# finished 시그널 발생
self.finished.emit()
2) Thread 수행 코드
def ThreadStart(self) :
# thread 생성
self.thread = Thread()
# thread의 finished 시그널 발생시 thread 종료
self.thread.finished.connect(self.thread.quit)
self.thread.finished.connect(self.thread.deleteLater)
# thread의 run 메소드 수행
self.thread.start()
해당 함수 부분만 별도 thread로 수행 시키면 gui 프리징 현상 없이 정상적으로 잘 동작할 겁니당
혹시 관련해서 궁금한 부분 있으시면 댓글 주세요~
※ 좋아요와 구독은 큰 힘이 됩니다. 감사합니다.
'파이썬 개발 > Qypt5' 카테고리의 다른 글
PyQt5 - GUI, Window 종료시 오류 내용 표시, 오류 정보 없는 프로그램 종료(Crash) 방지 (0) | 2022.09.14 |
---|---|
PyQt5 - QFileDialog.getOpenFileName 파일 선택후 파일명 가져와서 라인 에디터에 입력하기 (0) | 2022.08.09 |
PyQt5 - QLabel(레이블) 글자 잘림 현상 해결 (0) | 2022.08.08 |
PyQt5 - 어플리케이션, 위젯, 윈도우, 이벤트 루프에 대해서 (0) | 2022.08.03 |
PyQt5 - 메인 윈도우에서 다른 윈도우 열기 (0) | 2022.08.03 |
댓글