본문 바로가기
프로그래밍/Python

PyInstaller ] 파이썬 스크립트(.py)를 실행파일(.exe)로 만들기

by eteo 2024. 8. 12.

 

 

 

PyInstaller는 파이썬 스크립트를 파이썬 인터프리터가 설치되지 않은 환경에서도 실행이 가능하도록 실행 파일로 만들어 배포할 수 있게 해주는 패키지이다. 

 

 

 

 

 

PyInstaller 설치

 

pip install pyinstaller

 

 

 

 

PyInstaller 기본 사용법

 

실행 파일로 만들려는 파이썬 스크립트를 지정하여 PyInstaller를 실행한다.

pyinstaller example.py

 

 

 

 

 

 

PyInstaller로 생성되는 주요 폴더와 파일

 

project_root/
├── example.py                	  # PyInstaller로 패키징할 Python 스크립트
├── build/                        # 빌드 과정에서 생성된 임시 파일들
│   └── ...                       
├── dist/                         # 최종 배포용 파일이 생성되는 디렉토리
│   └── example/                  # 빌드한 스크립트와 종속성이 포함된 디렉토리
│       ├── example.exe           # 생성된 실행 파일
│       └── _internal/            # 실행 파일이 필요로 하는 라이브러리 및 종속성 폴더
│           └── ... 
├── example.spec                  # PyInstaller 설정 파일
└── ...

 

  • build 폴더 : 중간 빌드 파일을 저장하는 임시 디렉토리로 빌드 완료 후 삭제해도 무방하다.
  • dist 폴더 : 최종 배포용 실행파일이 이 폴더 안 <filename> 폴더 안에 생성된다.
  • dist/<filename>/_internal 폴더 : 이 폴더에는 실행파일을 실행하는데 필요한 모든 라이브러리와 종속성 및 Python 인터프리터가 포함된다.
  • .spec 파일 : PyInstaller 빌드 프로세스에 사용되는 설정 파일로 필요에 따라 이 파일을 수정하여 빌드 과정을 커스터마이즈할 수 있다.

 

 

 

배포시 고려사항

 

PyInstaller 기본 사용법을 통해 생성된 실행파일은 _internal 폴더에 의존하기 때문에 반드시 _internal 폴더를 실행파일과 동일 경로에 두어 배포해야한다.

또한 실행파일이 어플리케이션 내에서 상대경로로 리소스를 참조하고 있다면 해당 리소스 또는 리소스가 담긴 폴더를 같이 배포해야한다.

 

 

 

 

단일 실행파일 생성 옵션

 

위에 실행파일을 올바르게 동작시키기 위해서는 _internal 폴더를 같이 배포해야한다고 했는데 '--onefile' 또는 '-F' 옵션을 사용하면 모든 종속성이 하나의 실행파일에 포함되어 배포가 더 간편해질 수 있다. 아래와 같이 해당 옵션을 사용해 빌드한 경우 dist 폴더 안에 바로 <filename>.exe 실행파일이 생성되고 _internal 폴더는 생성되지 않는다. 다만 이렇게 배포하면 실행파일의 용량이 매우 커지고 실행시키는데 몇초~몇십초간의 딜레이가 있어 선호하는 방식은 아니다.

pyinstaller -F example.py

 

 

 

 

콘솔창 숨기기 옵션

 

'--windowed' 또는' --noconsole' 또는 '-w' 옵션을 사용하면 콘솔창을 표시하지 않을 수 있으며 기본적으로 사용하는 옵션이다.

pyinstaller -w example.py

 

 

 

 

아이콘 지정 옵션

 

'--icon' 옵션을 사용하여 .ico 파일이 위치한 경로를 지정하면 아이콘이 실행파일에 포함되어 적용된다.

pyinstaller --icon=path/to/icon.ico example.py

 

 

 

 

 

 

리소스 포함 옵션

 

위에서 실행파일 배포시 리소스도 같이 배포해야 된다고 했는데 '--add-data' 옵션을 사용하여 리소스를 실행파일에 포함시키는 방법도 있다. 

 

✔️ 윈도우에서는 리소스경로와 대상경로를 구분하는데 세미콜론(;)을 쓰고 리눅스에서는 콜론(:)을 구분자로 사용한다.

pyinstaller --add-data="리소스경로;대상경로" example.py
pyinstaller --add-data="Resources/*;Resources" example.py
pyinstaller --add-data="Resources/*;Resources" --add-data="imgs/*;imgs" example.py

 

✔️ 단, 이렇게 리소스를 실행파일에 포함시키면 타겟 PC에서 실행파일 실행 시 C:\Users\<user>\AppData\Local\Temp\ 경로 안에 임시 디렉터리가 생성되고 해당 디렉터리 안에 실행파일에 포함된 리소스 등이 복사된다. 따라서 해당 경우에는 애플리케이션이 올바른 경로에서 리소스를 참조할 수 있도록 코드를 수정해야 한다.

개인적으로는 굳이 리소스를 실행파일에 포함시키지 않고 실행파일과 같이 배포하는게 나을 것 같다.

import sys
import os

# 리소스가 최상위 경로에 있는 경우 가정
def resource_path(relative_path):		
    if hasattr(sys, '_MEIPASS'):
    	# 실행 파일로 패키징된 경우 임시 디렉터리에서 리소스를 찾음
        base_path = sys._MEIPASS
    else:
    	# 개발 중에는 현재 디렉터리에서 리소스를 찾음
        base_path = os.path.abspath(".")

    return os.path.join(base_path, relative_path)

# 리소스 파일의 전체 경로 획득
image_path = resource_path('image.png')
# 리소스 파일 사용
print(f"Image path: {image_path}")

 

참고로 sys._MEIPASS는 Python에서 PyInstaller로 패키징된 애플리케이션이 생성한 임시 디렉토리를 가리키기 위해 사용하는 속성이다.

 

 

 

 

 

실행파일을 실행시키자 마자 바로 종료되는 경우

 

cmd창에서 해당 실행파일을 실행시켜 오류문구를 보고 원인을 수정하면 된다.

 

 

 

 

 

 

실행파일의 용량이 너무 큰 경우

 

pyinstaller로 만든 실행파일의 크기는 설치된 패키지와 밀접한 관련이 있다. 실행파일의 용량이 크다면 너무 많은 패키지가 깔려있진 않은지 확인해보자.

특히 아나콘다는 데이터 과학을 위한 무거운 패키지들이 사전 설치된 형태로 배포되기 때문에 아나콘다가 설치된 상태에서 pyinstaller로 만드는 실행파일의 용량은 매우 클 것이다.

pip list

 

 

이 때 용량을 줄이기 위해 취할 수 있는 방법이 몇가지 있다.

 

1. 순정 파이썬을 설치하고 이를 PATH에 등록한 후 PyInstaller와 실행 파일 생성에 필요한 필수 패키지만 설치하여 실행 파일을 만든다. 작업이 완료되면 순정 파이썬을 삭제한다.

 

2. 아나콘다에 설치된 패키지를 전부 삭제하고 PyInstaller와 실행 파일 생성에 필요한 필수 패키지만 설치하여 실행 파일을 만든다. 작업이 완료되면 아나콘다를 재설치한다.

pip freeze > requirements.txt
pip uninstall -r requirements.txt -y
pip install -r requirements.txt

 

3. 가상환경을 생성하고 PyInstaller와 실행 파일 생성을 위한 필수 패키지만 설치하여 실행파일을 만든다. 작업이 완료되면 가상환경을 빠져나온다.

python -m venv myenv
cd myenv\Scripts
activate
(myenv) ~ 가상환경에서 작업 ~
deactivate.bat