Skip to content

PyInstaller

PyInstaller freezes (packages) Python applications into stand-alone executables, under Windows, GNU/Linux, Mac OS X, FreeBSD, Solaris and AIX.

Options

-F, --onefile
Create a one-file bundled executable.
--clean
Clean PyInstaller cache and remove temporary files before building.

Windows And Mac Os X Specific Options

-w, --windowed, --noconsole
Windows and Mac OS X: do not provide a console window for standard i/o.
On Mac OS this also triggers building a Mac OS .app bundle.
On Windows this option is automatically set if the first script is a .pyw file.
This option is ignored on *NIX systems.
-i ICON , --icon ICON
ICON is FILE.ico or FILE.exe,ID or FILE.icns or Image or NONE
  • FILE.ico: apply the icon to a Windows executable.
  • FILE.exe,ID: extract the icon with ID from an exe.
  • FILE.icns: apply the icon to the .app bundle on Mac OS.
  • Image: If an image file is entered that isn’t in the platform format (ico on Windows, icns on Mac), PyInstaller tries to use Pillow to translate the icon into the correct format (if Pillow is installed).
  • NONE to not apply any icon, thereby making the OS show some default (default: apply PyInstaller’s icon).
This option can be used multiple times.

Hide console window

콘솔창이 출력되지 않게 하려면 아래와 같이 명령어에 -w 또는 --windowed를 추가해줍니다.

pyinstaller -w qtextbrowser_advanced.py

Single executable

실행파일 하나만 생성하기 위해서는 아래와 같이 명령어에 -F 또는 –onefile을 추가합니다.

pyinstaller -F qtextbrowser_advanced.py

아이콘 설정

pyinstaller --icon=./test.ico --onefile 파이썬 파일명.py

Using Spec Files

사양 파일을 수정하는 것이 유용한 네 가지 경우가 있습니다.

  • 앱과 데이터 파일을 묶고 싶을 때.
  • PyInstaller가 다른 소스에서 알지 못하는 런타임 라이브러리( .dll또는 파일)를 포함하려는 경우..so
  • 실행 파일에 Python 런타임 옵션을 추가하려는 경우.
  • 공통 모듈이 병합된 다중 프로그램 번들을 생성하려는 경우.

데이터 폴더 지정

pyinstaller -F --add-data "./res/data;data" yourtarget.py

multiprocessing in windows

다른플랫폼에서 multiprocessing을 지원하려면 freeze_support 함수를 사용해야한다. 실행하면 windows의 고정 지원에만 영향을 준다고 써있는데... exe파일로 만든 프로그램 실행시 꺼지는 프로세스를 고정한다 생각하면될듯.

if __name__ == "__main__":
    multiprocessing.freeze_support()

UPX 적용 방법

Package Data

Generate Pyinstaller binaries

일반적으로 다음 명령을 사용하여 pyinstaller에서 실행 가능한 하나의 파일을 생성합니다.

$pyinstaller --onefile --clean <file_name.py>

pyinstaller 실행 파일에 데이터 파일 추가

실행 파일과 함께 압축해야 하는 응용 프로그램에 대한 도움말 파일이 있다고 가정해 보겠습니다. 애플리케이션은 런타임에 파일을 읽고 사용자에게 표시해야 합니다.

어떻게 하죠? 파일은 패키징하는 동안 애플리케이션의 일부로 존재하지만 바이너리와 함께 패키징되지 않습니다. 따라서 실행 중에 다음과 같은 오류가 발생할 수 있습니다.

FileNotFoundError: [Errno 2] No such file or directory:C:\\Users\\Username\\AppData\\Local\\Temp\\_MEI41602\\help.md
[11200] Failed to execute script

이는 pyinstaller 실행 파일이 XXXX가 임의의 숫자인 임시 디렉토리 _MEIXXXX에서 데이터 파일을 찾기 때문입니다. 모든 지원 데이터 파일이 거기에 복사되었는지 확인해야 합니다.

Pyinstaller는 임시 폴더에 데이터 압축을 풀고 이 디렉토리 경로를 MEIPASS 변수에 저장합니다. 이 속성은 부트로더에 의해 sys 환경에서 설정됩니다.

MEIPASS 변수는 프로그램이 번들 모드에서 실행 중인 경우에만 사용할 수 있습니다. 또한 프로그램이 번들에서 실행되는지 소스 코드에서 실행되는지 확인하는 데 도움이 됩니다.

Windows

$pyinstaller --onefile --clean --add-data "help.md;." <file_name.py>

Here we pass the file path to the add data flag with the path inside the bundle separated by a semi colon.

Linux/Mac

$pyinstaller --onefile --clean --add-data "help.md:." <file_name.py>

Here we pass the file path to the add data flag with the path inside the bundle separated by a colon.

Spec file

The data files can be added via spec files as well.

a = Analysis(...
     datas=[ ('help.md', '.') ],
     ...
     )

datas는 첫 번째 문자열이 기존 파일이 help.md임을 나타내는 튜플입니다. 해당 파일은 사양 파일의 위치를 기준으로 조회되고 번들 앱의 최상위 수준으로 복사됩니다. 이 경우 도움말 파일은 현재 디렉터리에 있습니다.

이제 도움말 데이터 파일을 pyinstaller 바이너리에 추가했으므로 이를 읽고 사용자에게 표시하는 방법은 무엇입니까?

먼저 소스 코드와 번들 모드 모두에서 도움말 파일을 읽을 수 있는지 확인해야 합니다. 앞서 언급했듯이 프로그램이 소스 코드 또는 pyinstaller에서 실행 중인지 확인할 수 있습니다.

def read_help_file():
    # Check if MEIPASS attribute is available in sys else return current file path
    bundle_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__)))
    path_to_help = os.path.abspath(os.path.join(bundle_dir,'help.md'))
    with open(path_to_help, "r+") as help_file:
        print(help_file.read())

Troubleshotting

_tkinter.TclError: invalid command name "PyImagingPhoto"

tkinter를 사용할 때 PIL과 같이 사용할 때 다음과 같은 에러 출력:

Traceback (most recent call last):
  File "PIL/ImageTk.py", line 181, in paste
_tkinter.TclError: invalid command name "PyImagingPhoto"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "magic-collection-tracker/test.py", line 22, in <module>
  File "magic-collection-tracker/test.py", line 11, in main
  File "PIL/ImageTk.py", line 120, in __init__
  File "PIL/ImageTk.py", line 185, in paste
ModuleNotFoundError: No module named 'PIL._tkinter_finder'

hiddenimports를 사용하여 해결하자.

hiddenimports=['PIL', 'PIL._imagingtk', 'PIL._tkinter_finder']

UPX is not available

UPX (실행파일 압축) 부터 설치하자.

See also

Favorite site