파이썬

파이썬) pyinstaller로 PyQt5.ui 파일 포함해서 실행파일 만들기

이소금 2022. 4. 2. 01:20
반응형

안녕하세요~!

오랜만에 글을 씁니다. 요 근래 문제 해결에만 집중하고 글로 정리하지 않았다 보니 학습했던것들이 대부분 휘발되네요..ㅠㅠ 글로 정리하는 것이 이렇게 중요한 것 같습니다.

최근 PyQT5로 배포용 응용 프로그램을 하나 만들었는데요, 스크립트에서는 잘 실행되나 pyinstaller로 exe 파일로 변환 시 정상적으로 동작하지 않았습니다.

 

문제 원인

QtDesinger 툴을 통해서 UI를 먼저 잡고 이 파일을 파이썬 코드와 연결했는데 pyinstaller로 묶을 때는 ui 파일이 같이 패키징 되지 않아 ui 파일을 찾을 수 없다는 오류가 계속 발생했습니다.

 

해결 방법

1. Before

보통 ui 연결 시에 아래처럼 연결하실텐데요,

from fileinput import filename
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets, uic

form_class = uic.loadUiType("파일명.ui")[0]

class MyWindow(QtWidgets.QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.initUI()

2. After

아래 코드 블럭을 사이에 넣어주세요. 

from fileinput import filename
import sys
from PyQt5.QtWidgets import *
from PyQt5 import QtWidgets, uic

########################################
import sys
import os

def resource_path(relative_path):
    """ Get absolute path to resource, works for dev and for PyInstaller """
    base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base_path, relative_path)

form = resource_path("파일명.ui")
form_class = uic.loadUiType(form)[0]

########################################
class MyWindow(QtWidgets.QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.initUI()

exe파일로 만드는 목적이 무엇인가요, 바로 배포를 하기 위해서입니다.

코드 개발 시에 ui 파일 위치를 제 컴퓨터에 저장된 디렉토리로 설정하게 되면 배포 시에 오류가 날테지요. 그러니 파일 위치를 고정값으로 지정해주는 함수를 넣어 ui 파일을 넘겨서 loaduiType에 연결시켜줍니다.

그리고 저장,

저는 아이콘을 넣을 것이니 아래 명령어로 pyinstaller를 실행시켰습니다.

$ pyinstaller --icon=아이콘.ico 파일명.py

코드 실행이 모두 끝나고 나면 build, dist 파일이랑 spec 파일이 새로 생긴걸 확인하실 수 있습니다.

업데이트 해줄 파일은 .spec 파일입니다. 현재는 ui 파일이 같이 패키징 되어 있지 않기 때문에 spec 파일에서 해당 ui 파일을 포함한다는 것을 알려줘야 합니다.

이 파일을 수정해 보겠습니다.

처음 spec 파일을 오픈했을 때는 datas 안에 아무것도 없을텐데요, 이걸 튜플 형식으로 작성해서 넣어주어야 합니다.

('파일명.ui', '.')

위 형식 그대로 가져다 datas의 리스트 안에 넣어줍니다.

저장해 주시고, 아래 커맨드 날려서 수정한 spec파일로 다시 빌드해줍니다.

 

$ pyinstaller --onefile 파일명.spec

실행을 하고 좀 기다리다 보면 아래와 같은 질문이 뜹니다.

WARNING: The output directory "디렉토리명" and ALL ITS CONTENTS will be REMOVED! Continue? (y/N)

우리는 Y로 갑니다. 어떤 뜻이냐면 수정된 파일로 덮어쓸건데 이전에 생성한 파일을 지워도 되냐 물어보는건데요, Y 해주시면 수정된 파일로 파일이 업데이트 되게 됩니다.

602874 INFO: Building COLLECT COLLECT-00.toc completed successfully

끝났습니다. 작동이 잘 되는지 한번 볼까요?

파일은 dist 폴더 안에 있습니다. 지정한 이모티콘도 잘 생성 되었구요. 프로그램도 잘 실행되는것 확인하실 수 있습니다.

그리고 이 파일들 중에, 아래와 같이 패키징 안에 ui 파일도 같이 묶인걸 확인하실 수 있습니다. 이후 배포하실 때 저 파일도 같이 전달되게 되니 배포 받는 사람도 무리 없이 파일 사용할 수 있겠죠?

그럼 오늘도 즐코하세요~!!!!

반응형