# 【pyinstaller】將Python程式打包成執行檔 > Lee Tsung Tang > ###### tags: `python` `pyinstaller` [TOC] {%hackmd @88u1wNUtQpyVz9FsQYeBRg/r1vSYkogS %} 因為要開發一個桌面應用給別人使用,因此研究了一下打包python的方式。`pyinstaller`應該是其中最方便的工具。 # 重點 - How PyInstaller can simplify application distribution - How to use PyInstaller on your own projects # Introduction 一般來說如果要把程式給別人使用時,需要先安裝python、安裝套件、虛擬環境....之後才能開始使用,但`pyinstaller` 可以簡單的將python程式打包成執行檔,方便任何人在不同環境中使用。 - `pyInstaller` 會編譯python code並將所有依賴的套件打包,使用者不需要額外處理環境問題。 - `pyInstaller`可以包裝成 Windows(.exe), Linux(regular executable), or macOS(.app)的執行檔 # Using PyInstaller install PyInstaller from `PyPI`. ```shell= pip install pyinstaller ``` > 如果是純python dependencies的程式編譯成執行檔的機會更高,但多數時候`C`/`C++` extensions 也能編譯成功。 > 例如常見的`NumPy`, `PyQt5`, and `Matplotlib`等套件,`pyinstaller`都能支援。詳細的套件支援狀況可以參見[pyinstaller documentation](https://github.com/pyinstaller/pyinstaller/wiki/Supported-Packages)。 >即使不在支援列表上的套件,多數打包時不會有任何問題。 ## 執行步驟 To try creating an executable with ==all the defaults==, simply give PyInstaller the name of your main entry-point script. 1. cd 到對應的資料夾 2. `$ pyinstaller your.py` # Digging Into PyInstaller Artifacts PyInstaller 編譯完會在指定路徑生成一大堆 output。對使用者來說大部分的output都不重要,只需要知道找到真正的執行檔就好,但為了對`pyinstaller`有更全面的了解,以下會簡單說明。 > 預設狀態下,`pyinstaller`會生成3個文件/檔案 - A *.spec file - A build/ folder - A dist/ folder ## Spec File > spec file 預設以編譯的py檔檔名命名,例如`main.py` >> `main.spec` > :warning: 以下的例子都是編譯`main.py`的結果 This file can be ==modified and re-used to create executables later==. You can make future builds a bit faster by providing this spec file instead of the entry-point script to the pyinstaller command. There are a few specific use-cases for PyInstaller spec files. However, for simple projects, *you won’t need to worry about those details unless you want to heavily customize how your project is built*. ## Build Folder build folder的資料夾結構如下 ``` build/ | └── main/ ├── Analysis-00.toc ├── base_library.zip ├── COLLECT-00.toc ├── EXE-00.toc ├── PKG-00.pkg ├── PKG-00.toc ├── PYZ-00.pyz ├── PYZ-00.toc ├── warn-main.txt └── xref-main.html ``` > build folder主要用來儲存建構執行檔的metadata以及各種內部紀錄文件 > >The build folder can be useful for **debugging**, but unless you have problems, this folder ==can largely be ignored==. ## Dist Folder 資料夾架構 ``` dist/ | └── main/ └── main ``` dict folder內會有一個以主程式為名的資料夾(此處主程式為`main.py`)。main folder內包執行檔(用以執行app)以及其他相依的檔案。 > The executable to run is ==dist/main/main or dist/main/main.exe if you’re on Windows==. > > 要執行app需要在發布時包含完整的dist/main folder # Customizing Your Builds 簡單介紹幾個實用的參數 - -h, --help 查看可用的參數 ```shell= $ pyinstaller -h ``` <br/> - -n, --name 將所有原本以主程式命名的檔案更名 ```shell= $ pyinstaller main.py --name APP ``` <br/> - -F, --onefile 打包成單一檔案(只有一個執行檔) ```shell= $ pyinstaller cli.py --onefile ``` With the above command, your dist/ folder will only contain a single executable instead of a folder with all the dependencies in separate files. <br/> - -w 使用視窗,無控制台 ```shell= $ pyinstaller main.py -w ``` <br/> - -c, –console 使用控制台,無視窗 <br/> - -i, –icon 可執行檔案的圖示 # RecursionError: maximum recursion depth exceeded 打包時很常遇到的error `RecursionError: maximum recursion depth exceeded` 解決方法是在spec檔最前面加上 ```python= import sys sys.setrecursionlimit(5000) ``` 限制遞迴的次數上限 接著以spec檔打包 ```shell= pyinstaller myapp.spec ``` <br/> <br/> <br/> :::info 其他debug或無法編譯的問題可以參考下面的資料 ::: # 參考資料 [PyInstaller Manual](https://pyinstaller.readthedocs.io/en/stable/index.html) [Using PyInstaller to Easily Distribute Python Applications](https://realpython.com/pyinstaller-python/#pyinstaller) [【Python】將Python打包成exe檔](https://medium.com/pyladies-taiwan/python-%E5%B0%87python%E6%89%93%E5%8C%85%E6%88%90exe%E6%AA%94-32a4bacbe351)