PyInstaller를 사용하여 Python 실행 파일을 만드는 방법

강력하고 다재다능한 Python은 기본적으로 몇 가지 핵심 기능이 부족합니다. 우선, Python은 Python 프로그램을 독립 실행 형 실행 패키지로 컴파일하기위한 기본 메커니즘을 제공하지 않습니다.

공정하게 말하면 Python의 원래 사용 사례에서는 독립 실행 형 패키지를 호출하지 않았습니다. Python 프로그램은 대체로 Python 인터프리터 사본이있는 시스템에서 제자리에서 실행되었습니다. 그러나 Python의 급증하는 인기로 인해 Python 런타임이 설치되지 않은 시스템에서 Python 앱을 실행해야하는 수요가 증가했습니다.

여러 타사에서 독립 실행 형 Python 앱 배포를위한 솔루션을 설계했습니다. 가장 인기 있고 가장 성숙한 솔루션은 PyInstaller입니다. PyInstaller는 Python 앱을 패키징하는 과정을 완전히 고통스럽지 않게 만들지는 않지만 거기에는 먼 길을갑니다.

이 기사에서는 PyInstaller의 작동 방식, PyInstaller를 사용하여 독립 실행 형 Python 실행 파일을 만드는 방법, 생성 한 Python 실행 파일을 미세 조정하는 방법, 발생하는 일반적인 함정을 피하는 방법을 포함하여 PyInstaller 사용의 기본 사항을 살펴 봅니다. PyInstaller를 사용하여.

PyInstaller 패키지 만들기

PyInstaller는 pip( pip install pyinstaller) 와 함께 설치되는 Python 패키지 입니다. PyInstaller는 기본 Python 설치에 설치할 수 있지만 PyInstaller를 패키징하고 설치하려는 프로젝트에 대한 가상 환경을 만드는 것이 가장 좋습니다.

PyInstaller는 Python 프로그램을 읽고 모든 가져 오기를 분석하고 해당 가져 오기 사본을 프로그램과 번들로 묶는 방식으로 작동합니다. PyInstaller는 진입 점에서 프로그램을 읽습니다. 프로그램의 진입 점 인 경우 예를 들어 myapp.py, 당신은 실행됩니다 pyinstaller myapp.py분석을 수행 할 수 있습니다. PyInstaller는 NumPy와 같은 많은 일반적인 Python 패키지를 감지하고 자동으로 패키징 할 수 있지만 경우에 따라 힌트를 제공해야 할 수도 있습니다. (이 내용은 나중에 자세히 설명합니다.)

코드를 분석하고 사용하는 모든 라이브러리와 모듈을 찾은 후 PyInstaller는 "사양 파일"을 생성합니다. 확장자가 .spec인 Python 스크립트 인이 파일에는 Python 앱을 압축하는 방법에 대한 세부 정보가 포함되어 있습니다. 앱에서 PyInstaller를 처음 실행하면 PyInstaller가 처음부터 사양 파일을 생성하고 정상적인 기본값으로 채 웁니다. 이 파일을 버리지 마십시오. PyInstaller 배포를 다듬는 열쇠입니다!

마지막으로 PyInstaller는 모든 종속성과 함께 번들로 제공되는 앱에서 실행 파일을 생성하려고 시도합니다. 완료되면 이름이 지정된 하위 폴더 dist (기본적으로 다른 이름을 지정할 수 있음)가 프로젝트 디렉토리에 나타납니다. 여기에는 번들 앱인 디렉토리가 포함됩니다. 여기에는 .exe실행할 파일과 필요한 모든 라이브러리 및 기타 추가 파일이 있습니다.

프로그램을 배포하기 위해해야 ​​할 일은이 디렉토리를 .zip파일이나 다른 번들 로 패키지화하는 것 입니다. 번들은 일반적으로 실행하려면 사용자에게 쓰기 권한이있는 디렉토리에서 추출해야합니다.

PyInstaller 패키지 테스트

PyInstaller를 사용하여 앱을 패키징하려는 첫 번째 시도가 완전히 성공하지 못할 가능성이 있습니다.

PyInstaller 패키지가 작동하는지 확인하려면 번들로 제공되는 실행 .exe파일이 포함 된 디렉터리로 이동 하여 명령 줄에서 파일을 실행하십시오 . 실행에 실패하면 명령 줄에 인쇄 된 오류가 무엇이 잘못되었는지에 대한 힌트를 제공해야합니다.

PyInstaller 패키지가 실패하는 가장 일반적인 이유는 PyInstaller가 필수 파일을 번들링하지 못했기 때문입니다. 이러한 누락 된 파일은 몇 가지 범주로 나뉩니다.

  • 숨겨 지거나 누락 된 가져 오기 : 일반적으로 동적으로 가져 오기 때문에 PyInstaller가 패키지 또는 라이브러리 가져 오기를 감지하지 못하는 경우가 있습니다. 패키지 또는 라이브러리는 수동으로 지정해야합니다.
  • 누락 된 독립 실행 형 파일 : 프로그램이 프로그램과 함께 번들로 제공되어야하는 외부 데이터 파일에 의존하는 경우 PyInstaller는 알 수 없습니다. 파일을 수동으로 포함해야합니다.
  • 누락 된 바이너리 : 여기서도 PyInstaller가 감지 할 수없는 .DLL과 같은 외부 바이너리에 프로그램이 의존하는 경우 수동으로 포함해야합니다.

좋은 소식은 PyInstaller가 위의 문제를 쉽게 처리 할 수있는 방법을 제공한다는 것입니다. .specpyInstaller 중에 만든 파일은 우리가 pyInstaller 중에 놓친 그 세부 사항을 제공하기 위해 채울 수있는 필드가 포함되어 있습니다.

.spec텍스트 편집기에서 파일을 열고 Analysis개체 의 정의를 찾습니다 . 전달 된 매개 변수 중 일부 Analysis는 빈 목록이지만 누락 된 세부 사항을 지정하기 위해 편집 할 수 있습니다.

  • hiddenimports숨겨진 가져 오기 또는 누락 된 가져 오기 : 앱에 포함하려는 라이브러리 이름이있는 하나 이상의 문자열을이 목록에 추가합니다. 추가 싶었다면 pandasbokeh예를 들어, 당신은 그것을 지정합니다  ['pandas','bokeh']. 해당 라이브러리는 PyInstaller를 실행하는 동일한 Python 인스턴스에 설치 되어야합니다 .
  • datas누락 된 독립 실행 형 파일 : 여기에 프로젝트에 포함 할 프로젝트 트리의 파일에 대한 하나 이상의 사양을 추가합니다. 각 파일은 프로젝트 디렉터리의 파일에 대한 상대 경로와 파일을 배치 할 배포 디렉터리 내의 상대 경로를 나타내는 튜플로 전달되어야합니다. 예를 들어 ./models/mainmodel.dat앱에 포함하려는 파일 이 있고 배포 디렉터리의 일치하는 하위 디렉터리에 배치하려는 ('./models/mainmodel.dat','./models')경우 hiddenimports목록 에서 하나의 항목으로 사용 합니다. glob-style 와일드 카드를 사용하여 둘 이상의 파일을 지정할 수 있습니다 .
  • binaries독립 실행 형 바이너리가 누락 된 경우 :와 마찬가지로를 datas사용 binaries하여 프로젝트 트리의 바이너리 위치와 배포 디렉토리의 대상을 지정하는 튜플 목록을 전달할 수 있습니다 . 다시 말하지만, glob-style 와일드 카드를 사용할 수 있습니다 .

전달 된 모든 목록 Analysis.spec파일의 초기에 프로그래밍 방식으로 생성 될 수 있습니다 . 결국 .spec파일은 다른 이름의 Python 스크립트입니다.

.spec파일 을 변경 한 후 PyInstaller를 다시 실행하여 패키지를 다시 빌드하십시오. 그러나 이제부터는 수정 된 .spec파일을 매개 변수 (예 :)로 전달해야합니다 pyinstaller myapp.spec. 이전과 같이 실행 파일을 테스트하십시오. 여전히 문제가있는 경우 .spec파일을 다시 편집하고 모든 것이 작동 할 때까지 프로세스를 반복 할 수 있습니다.

마지막으로 모든 것이 의도 한대로 작동하는 것이 만족 스러우면 .spec패키지 된 앱이 시작될 때 명령 줄 창을 표시하지 않도록 파일을 편집 할 수 있습니다  . 파일  의 EXE개체 설정에서 . 콘솔을 억제하는 것은 앱에 GUI가 있고 사용자를 잘못된 길로 안내하는 가짜 명령 줄 창을 원하지 않는 경우에 유용합니다. 물론 앱에 명령 줄이 필요한 경우이 설정을 변경하지 마십시오..specconsole=False

PyInstaller 패키지 수정

앱이 PyInstaller로 패키징되고 제대로 실행되면 다음으로 할 일은 조금 줄이는 것입니다. PyInstaller 패키지는 날렵한 것으로 알려져 있지 않습니다.

Python은 동적 언어이기 때문에 주어진 프로그램에서 런타임에 필요한 것이 무엇인지 예측하기가 어렵습니다. 따라서 PyInstaller가 패키지 가져 오기를 감지하면 실제로 프로그램에서 런타임에 사용되는지 여부에 관계없이 해당 패키지의 모든 항목 이 포함됩니다 . 

여기 좋은 소식이 있습니다. PyInstaller에는 전체 패키지 또는 패키지 내의 개별 네임 스페이스 를 선택적으로 제외하는 메커니즘이 포함되어 있습니다 . 예를 들어 프로그램이 및 foo을 포함하는 package를 가져 왔다고 가정 해 보겠습니다 . 프로그램이에서 논리 만 사용한다는 사실을 알고 있다면 안전하게 제외  하고 일부 공간을 절약 할 수 있습니다 .foo.barfoo.bipfoo.barfoo.bip

이렇게하려면 파일 excludesAnalysis개체에 전달 된 매개 변수 를 사용 .spec합니다. 이름 목록 (최상위 모듈 또는 점으로 구분 된 네임 스페이스)을 전달하여 패키지에서 제외 할 수 있습니다. 예를 들어를 제외 foo.bip하려면을 지정하면  ['foo.bip']됩니다.

한 가지 일반적인 제외는 tkinter간단한 크로스 플랫폼 그래픽 사용자 인터페이스를 만들기위한 Python 라이브러리입니다. 기본적으로  tkinter모든 지원 파일은 PyInstaller 프로젝트에 포함되어 있습니다. tkinter프로젝트에서 사용하지 않는 경우 목록 에 추가 'tkinter'하여 제외 할 수 있습니다 excludes. 생략 tkinter하면 패키지 크기가 약 7MB 줄어 듭니다.

또 다른 일반적인 제외는 테스트 스위트입니다. 프로그램이 가져 오는 패키지에 테스트 스위트가있는 경우 테스트 스위트는 결국 PyInstaller 패키지에 포함될 수 있습니다. 배포 된 프로그램에서 실제로 테스트 스위트를 실행하지 않는 한 안전하게 제외 할 수 있습니다.

제외를 사용하여 만든 패키지는 사용하기 전에 철저히 테스트해야합니다. 예상하지 못한 미래 시나리오에서 사용되는 기능을 제외하면 앱이 중단됩니다.

PyInstaller 팁

  • 배포하려는 OS에 PyInstaller 패키지를 빌드하십시오.  PyInstaller는 크로스 플랫폼 빌드를 지원하지 않습니다. MacOS, Linux 및 Windows 시스템에 독립형 Python 앱을 배포해야하는 경우 PyInstaller를 설치하고 이러한 각 운영 체제에 별도의 앱 버전을 빌드해야합니다. 
  • 앱을 개발하면서 PyInstaller 패키지를 빌드하세요.  PyInstaller를 사용하여 프로젝트를 배포 할 것이라는 사실을 알게되는 즉시 .spec파일을 빌드 하고 앱 개발과 동시에 PyInstaller 패키지를 수정하십시오. 이렇게하면 이동 중에 제외 또는 포함을 추가하고 새로운 기능을 작성할 때 앱과 함께 배포되는 방식을 테스트 할 수 있습니다.
  • PyInstaller의 --onefile모드를 사용하지 마십시오  .  PyInstaller에는 --onefile전체 앱을 하나의 자동 압축 풀기 실행 파일로 압축 하는 명령 줄 스위치가 포함되어 있습니다 . 좋은 생각처럼 들리 네요. 파일 하나만 전달하면됩니다! — 그러나 약간의 함정이 있습니다. 앱을 실행할 때마다 먼저 실행 파일 내의 모든 파일을 임시 디렉터리에 압축 해제해야합니다. 앱이 큰 경우 (예 : 200MB) 압축을 풀면 몇 초 정도 지연 될 수 있습니다. 대신 기본 단일 디렉토리 모드를 사용하고 모든 것을 .zip파일 로 압축 하십시오.
  • PyInstaller 앱용 설치 프로그램을 만듭니다.  .zip 파일이 아닌 다른 방법으로 앱을 배포하려면 오픈 소스 Nullsoft Scriptable Install System과 같은 설치 프로그램 유틸리티를 사용하는 것이 좋습니다. 결과물 크기에 약간의 오버 헤드를 추가하고 실행 파일에 대한 바로 가기 생성과 같은 설치 프로세스의 여러 측면을 구성 할 수 있습니다.
  • 속도 향상을 기대하지 마십시오.  PyInstaller는 패키징 시스템이지 컴파일러  나  옵티마이 저가  아닙니다  . PyInstaller로 패키지 된 코드는 원래 시스템에서 실행될 때보 다 더 빨리 실행되지 않습니다. Python 코드 속도를 높이려면 작업에 적합한 C 가속 라이브러리 또는 Cython과 같은 프로젝트를 사용하십시오.

Python으로 더 많은 작업을 수행하는 방법

  • Cython 튜토리얼 : 파이썬 속도를 높이는 방법
  • Python을 현명하게 설치하는 방법
  • Poetry로 더 나은 Python 프로젝트 관리
  • Virtualenv 및 Venv : Python 가상 환경 설명
  • Python virtualenv 및 venv해야 할 일과하지 말아야 할 일
  • Python 스레딩 및 하위 프로세스 설명
  • Python 디버거를 사용하는 방법
  • timeit을 사용하여 Python 코드를 프로파일 링하는 방법
  • cProfile을 사용하여 Python 코드를 프로파일 링하는 방법
  • Python에서 비동기 시작하기
  • Python에서 asyncio를 사용하는 방법
  • Python을 JavaScript로 변환하는 방법 (그리고 다시)