Python學習筆記:PyInstaller(exe程序打包)

PyInstaller能夠將Python程序打包成一個exe程序來獨立運行,用戶使用時只須要執行這個exe文件便可,不須要在機器上再安裝Python及其餘包就可運行了。另外,PyInstaller相較於其餘打包程序,好比py2exe,大多時候使用起來更加方便,能夠經過命令行的一些簡單命令便可進行打包,固然,當你須要打包的程序比較大且複雜時,使用哪一個打包程序可能差異都不會太大了,這時候就看我的的習慣和愛好了。python

pip安裝PyInstaller:pip install pyinstallershell

pip更新PyInstaller:pip install --upgrade pyinstaller小程序

pypi下載PyInstaller:https://pypi.org/project/PyInstaller/#fileswindows

注意:windows安裝PyInstaller時須要額外安裝另外兩個模塊,pywin32或pypiwin32,以及pefile,若是使用pip進行安裝,可是尚未安裝pywin32時,會自動安裝pypiwin32,pefile沒有時也會自動安裝。緩存

 

簡單打包命令eclipse

pyinstaller [-F/-D] [-w/-c] [-i xxx.ico] xxx.py/xxx.spec函數

  • xxx.py/xxx.spec:須要打包的程序main文件或者spec文件。spec文件在使用py文件進行打包時會在相同路徑下自動生成,spec中的內容也是根據命令行中輸入的內容來生成的,也可使用命令pyi-makespec [options] xxx.py來生成一個純粹的spec文件,而不會去執行打包的操做。
  • -F/--onefile:將整個程序打包爲一個exe文件,須要注意的是,與-D模式生成的exe程序相比,在啓動速度上會慢一點,緣由是它須要先解壓exe文件並生成一個惟一的臨時環境來運行程序,關閉環境時也會自動刪除這個臨時環境,-D模式的程序自己就是解壓好的,運行完也不須要執行刪除操做,當程序比較大時,這個差異就很明顯了。
  • -D/--onedir:默認選項,與F/--onefile參數做用相反,將程序打包爲一個文件夾,文件夾中包含啓動程序的exe文件和其餘依賴的資源文件和DLL文件等。
  • -w:表示程序運行後隱藏命令行窗口,當你不須要使用命令行窗口做爲程序的I/O時,好比GUI程序,可使用這個參數選項。
  • -c:默認選項,與-w相反,提供一個命令行窗口進行I/O。
  • -i/--icon:指定exe程序圖標。

 

通常來講,大多數的程序,特別是一些小程序,使用這個命令就能夠順利的打包了,也用不到其餘複雜的參數選項。若是須要其餘的知識點,如下的一些點能夠參考下(這些點是本身在官方文檔上找的,有些並無通過驗證,有錯歡迎指正):工具

命令行指定參數選項方式打包:ui

  1. build文件夾:運行後會在同路徑下生成一個build文件夾,這個文件夾的做用至關於PyInstaller的工做空間,PyInstaller運行相關的文件和日誌都在這個文件夾中,打包完成後能夠直接刪除。
  2. dist文件夾:運行完成後會在同路徑下生成一個dist文件夾,這個文件夾下有一個跟程序同名的文件夾,打包好的exe程序就在這個文件夾下。
  3. 多py文件:若是命令行中指定的py文件不止一個,好比「pyinstaller xxx1.py xxx2.py」,pyinstaller會依次分析並執行,並把第一個py名稱做爲spec和dist文件下的文件夾和程序的名稱。
  4. 其餘經常使用參數選項:
    • --specpath DIR:指定生成spec文件的路徑,默認爲當前路徑。
    • -n NAME/--name NAME:指定spec文件和程序的名稱,默認就是傳入的py腳本或spec文件的名稱。
    • -h/--help:顯示PyInstaller幫助信息。
    • -v/--version:顯示PyInstaller版本信息。
    • --distpath DIR:指定生成dist的目錄,默認爲「./dist」。
    • --workpath WORKPATH:指定pyinstaller的工做目錄,即build文件夾,默認爲「./build」。
    • -y/--noconfirm:替換輸出目錄時不詢問,默認輸出目錄是「SPECPATH/dist/SPECNAME」。
    • --upx-dir UPX_DIR:指定UPX程序的路徑,默認爲「程序執行路徑」,即雙擊某個文件時,系統自動查找對應程序的路徑。UPX爲一個壓縮程序,須要自行下載,能夠將exe壓縮爲zip格式的文件,而且壓縮效率很是高,若是打包後的exe程序很是大的話,爲了不客戶下載時文件太大的問題,可使用這個UPX工具。
    • --noupx:不須要UPX(即使可用)。
    • -a/--ascii:不支持Unicode,默認爲支持(若是可用的話)。
    • --clean:在pyinstaller開始執行以前清除緩存並刪除臨時文件(通常存儲在C:\Users\Administrator\AppData\Roaming\pyinstaller)。
    • --log-level LEVEL:指定打印的日誌等級,默認爲INFO,日誌等級有:TRACE,DEBUG,INFO,WARN,ERROR,CRITICAL。若是在打包時遇到了問題,爲了方便定位問題,可使用這個參數來查看特定級別的日誌信息。
  5. 數據綁定和搜索相關的參數選項:
    • --add-data SRC;DEST:指定須要添加非二進制文件路徑或者文件夾路徑,好比圖片和pdf文件等,這個選項可使用屢次。這個命令其實就是將須要的文件或者文件夾拷貝到指定的路徑下,在-D模式下,能夠看狀況在程序打包完成後本身手動拷貝過去。
    • --add-binary SRC;DEST:指定須要添加的二進制文件路徑,好比DLL文件、動態連接庫或者共享文件對象等,這個選項可使用屢次。同-add-data命令同樣,是一個拷貝數據的功能。
    • -p DIR/--paths DIR:指定import語句的查找路徑(與PYTHONPATH同樣),多個路徑之間可使用分號「;」鏈接,或者屢次使用這個選項來進行指定。
    • --hidden-import MODULENAME/--hiddenimport MODULENAME:指定腳本中須要隱式導入的模塊,好比在__import__、imp.find_module()、exec、eval等語句中導入的模塊,這些模塊PyInstaller是找不到的,須要手動指定導入,這個選項可使用屢次。
    • --additional-hooks-dir HOOKSPATH:指定額外hook文件(能夠是py文件)的查找路徑,這些文件的做用是在PyInstaller運行時改變一些Python或者其餘庫原有的函數或者變量的執行邏輯(並不會改變這些庫自己的代碼),以便能順利的打包完成,這個選項可使用屢次。
    • --runtime-hook RUNTIME_HOOKS:指定自定義的運行時hook文件路徑(能夠是py文件),在打好包的exe程序中,在運行這個exe程序時,指定的hook文件會在全部代碼和模塊以前運行,包括main文件,以知足一些運行環境的特殊要求,這個選項可使用屢次。
    • --exclude-module EXCLUDES:指定能夠被忽略的可選的模塊或包,由於某些模塊只是PyInstaller根據自身的邏輯去查找的,這些模塊對於exe程序自己並無用到,可是在日誌中仍是會提示「module not found」,這種日誌能夠不用管,或者使用這個參數選項來指定不用導入,這個選項可使用屢次。
    • --key KEY:指定用於Python字節碼加密的key,key是一個16個字符的字符串。
  6. -D模式程序的運行:運行程序的時候,其實開始運行的是一個pyinstaller生成的引導加載程序bootloader,bootloader是根據不一樣的操做系統生成的,運行bootloader時,會建立一個臨時的Python環境以便運行Python程序,因此使用exe程序時不用安裝Python也能運行這個程序。
  7. -F模式程序的運行:也會有一個BootLoader,可是會根據操做系統建立一個名爲_MEIxxxxxx的文件夾,用做這個程序的臨時運行環境(不僅是Python環境),這個xxxxxx是一個隨機的數字。-F模式程序啓動的時候由於須要解壓並拷貝依賴和資源文件到臨時運行環境_MEIxxxxxx,因此啓動速度是比-D模式程序要慢的,運行結束後會刪除臨時運行環境的文件夾。在Linux和相關係統中,可能有「no-execution」選項,可是對於-F模式程序是不兼容的。因爲_MEIxxxxxx是惟一的,因此能夠同時運行多個程序,多個程序時互不干涉的。若是程序崩潰了,或者強行結束了(好比在Windows的任務管理器中殺死了進程),_MEIxxxxxx文件夾是不會被刪除的,因此頻繁崩潰或者結束進程會致使有多個_MEIxxxxxx文件夾,會很是佔用磁盤空間,可使用--runtime-temdir指定_MEIxxxxxx的存放位置。-F模式程序若是在運行時遇到了權限問題,可使用-D模式程序替代。
  8. shell腳本/批處理腳本:使用命令行打包時,可能須要指定的參數選項不少,這時候能夠將須要執行的所有命令信息,包括這些參數選項的指定,都放在一個shell腳本或者批處理文件中來執行。
  9. 運行時信息:
    • __file__: 全部基於模塊的使用到__file__屬性的代碼,在源碼運行時表示的是當前腳本的絕對路徑,可是打包後就是當前模塊的模塊名(即文件名xxx.py)。
    • sys.frozen:源碼運行時沒有這個屬性,打包後的程序添加了這個屬性,值爲True。
    • sys._MEIPASS: 源碼運行時沒有這個屬性,打包後的程序添加了這個屬性,表示程序運行的絕對路徑。對於-D模式程序,表示的是這個exe程序所在文件夾的絕對路徑,對於-F模式程序表示的是_MEIxxxxxx的文件夾絕對路徑,_MEIxxxxxx爲exe解壓後建立的臨時運行環境的文件夾名稱,對於exe程序每一次運行來講,它是惟一的。
    • sys.excutable:代碼運行時表示運行的解釋器絕對路徑,如C:\Python36\python.exe,在打包的程序中就是exe程序文件的絕對路徑,這個是用來定位用戶運行該程序的真實位置。
    • sys.argv[0]:通常來講就是運行程序的絕對路徑,可是在不一樣平臺或者不一樣的方式啓動程序時,會有所不一樣,好比經過符號連接運行的程序sys.argv[0]就是符號名稱,而不是真實的程序路徑。
  10. 數據文件的修改:--add-data這種經過拷貝形式的數據文件,在-D模式下若是在運行時修改了,那麼對應的數據文件是真的被修改了,可是在-F模式下,因爲每次運行會單首創建一個臨時運行環境,修改的內容也是臨時運行環境中的內容,而且運行完後會自動刪除臨時運行環境,因此這種數據文件是沒法直接更改exe中的數據文件的,也就意味着每次運行程序,數據文件都會是exe程序中原來的那一份,修改的內容會隨着臨時運行環境的關閉而刪除了,不會同步到exe程序中的。
  11. 發生錯誤時:
    • 當發生「module not found」警告時,其實不少找不到對應模塊的消息都不用管,只是PyInstaller根據自身的邏輯去查找的,由於它們並非跟你的最終程序有關的。
    • 當發生導入失敗時,這纔是真正的錯誤,須要去關注和解決的。
    • 當打包成功,且中間沒有發生任何警告提示,可是運行程序時提示某個模塊找不到,可能就是「--hidden-import=」的問題了,當使用__import__、imp.find_module()、exec、eval或者Python/C API時,pyinstaller不會自動去導入這些裏面涉及的導包,因此這些包就須要使用「--hidden-import=」來指定具體須要導入的包了。
    •  --runtime-hook=xxx.py中指定的py會依次在打包的主程序main腳本以前運行,能夠用來改變一些函數或者變量,以知足特殊場景的要求。

 

spec配置文件方式打包加密

  1. 生成spec文件:pyi-makespec [options] xxx.py [other scripts...],生成spec文件時能夠什麼都不指定,而後在生成的spec文件中單獨配置,默認爲-D模式下的spec文件,也能夠指定生成-F模式的spec文件。固然也能夠在第一次就將參數選項指定好,之後就只維護spec文件。
  2. 參數選項:生成spec文件的參數選項和命令行模式下執行PyInstaller打包是徹底同樣的。
  3. spec文件類型:spec文件其實就是一個py文件,在編輯時能夠直接將它當成一個py文件來使用。
  4. spec文件優點:通常狀況而言,直接使用PyInstaller命令行直接打包便可,可是如下狀況使用spec文件的話會方便一些:
    • 程序須要綁定一些數據文件,能夠在spec文件中單獨用一個列表變量來指定,可讀性和可維護性會高不少。
    • 須要include一些PyInstaller不知道的動態連接庫,如:.dll/.so文件,一樣能夠在spec文件中單獨用一個列表變量來指定。
    • 須要往可執行文件中添加一些運行時選項,如hook文件。

關於spec文件:

    若是有須要,能夠經過PyCharm、eclipse等工具打開安裝目錄中的PyInstaller文件夾來查看源碼信息
    • a:Analysis類的實例,要求傳入各類腳本用於分析程序的導入和依賴。a中內容主要包括如下四部分:scripts,便可以在命令行中輸入的Python腳本;pure,程序代碼文件中的純Python模塊,包括程序的代碼文件自己;binaries,程序代碼文件中須要的非Python模塊,包括--add-binary參數指定的內容;datas,非二進制文件,包括--add-data參數指定的內容。
    • pyz:PYZ的實例,是一個.pyz文件,包含了全部pure中的全部Python模塊。
    • exe:EXE類的實例,這個類是用來處理Analysis和PYZ的結果的,也是用來生成最後的exe可執行程序。
    • coll:COLLECT類的實例,用於建立輸出目錄。在-F模式下,是沒有COLLECT實例的,而且全部的腳本、模塊和二進制文件都包含在了最終生成的exe文件中。
  1. Analysis參數scripts:也是第一個參數,它是一個腳本列表,能夠傳入多個py腳本,效果與命令行中指定多py文件相同,即py文件不止一個時,好比「pyinstaller xxx1.py xxx2.py」,pyinstaller會依次分析並執行,並把第一個py名稱做爲spec和dist文件下的文件夾和程序的名稱。
  2. Analysis參數pathex:同命令「-p DIR/--paths DIR」,其實默認就有一個spec的目錄,若是使用命令添加的話,會首先添加命令中指定的目錄,再添加默認的路徑。
  3. Analysis參數datas:即添加數據文件,命令是--add-data,spec文件中是Analysis的datas=[]參數,datas是一個元素爲元組的列表,每一個元組有兩個元素,都必須是字符串類型,元組的第一個元素爲數據文件或文件夾,元組的第二個元素爲運行時這些文件或文件夾的位置。例如:datas=[('src/README.txt', '.'), ],也能夠在命令行中這樣寫:pyinstaller --add-data 'src/README.txt;.' myscript.py,表示打包時將文件src/README.txt添加(copy)到相對於spec文件的根目錄下,指定文件時是相對於spec來進行尋找的,而不是要打包的exe程序路徑。也可使用通配符:datas= [ ('/mygame/sfx/*.mp3', 'sfx' ) ],表示將/mygame/sfx/目錄下的全部.mp3文件都copy到sfx文件夾中。也能夠添加整個文件夾:datas= [ ('/mygame/data', 'data' ) ],表示將/mygame/data文件夾下全部的文件都copy到data文件夾下。
  4. Analysis參數binaries:添加二進制文件,效果同命令--add-binary,也是一個列表,定義方式與datas參數同樣。
  5. Analysis參數hiddenimports:同命令「--hidden-import MODULENAME/--hiddenimport MODULENAME」。
  6. Analysis參數hookspath:同命令「--additional-hooks-dir HOOKSPATH」。
  7. Analysis參數runtime_hooks:同命令「--runtime-hook RUNTIME_HOOKS」。
  8. Analysis參數excludes:同命令「--exclude-module EXCLUDES」。
  9. exe參數console:設置是否顯示命令行窗口,和命令-w/-c做用同樣。
  10. exe參數icon:設置程序圖標,和命令-i/--icon做用同樣。某些狀況,直接執行「pyinstaller xxx.py」時生成的spec中沒有這個參數,須要手動添加,參數值就是圖片路徑的字符串。
  11. PyInstaller全局變量:這些全局變量能夠在spec文件使用。
    • DISTPATH:相對於dist文件夾的相對路徑,若是--distpath參數選項被指定了,則使用被指定的參數值。
    • HOMEPATH:pyinstaller查找的絕對路徑,通常是Python解釋器的site-packages文件夾的絕對路徑。
    • SPEC:在命令行中指定的spec文件路徑。
    • SPECPATH:os.path.split(SPEC)的第一個值。
    • specnm:spec文件的文件名,不含文件類型後綴。
    • workpath:相對於build文件夾的相對路徑,若是workpath=參數選項被指定了,這使用被指定的值。
    • WARNFILE:在build文件夾中警告文件的全路徑,通常是warn-myscript.txt
  12. 指定了相同的參數:當命令行和spec中指定了相同的參數選項,那麼命令行的參數選項會被忽略。

 

遇到的問題和解決方案:

1.問題描述:

打包時報以下異常:

File "c:\python36\lib\site-packages\PyInstaller\hooks\pre_safe_import_module\hook-setuptools.extern.six.moves.py", line 34, in pre_safe_import_module
for real_module_name, six_module_name in real_to_six_module_name.items():
AttributeError: 'str' object has no attribute 'items'

解決方案:

使用命令「pip install --upgrade setuptools」更新三方庫setuptools

相關文章
相關標籤/搜索