將python代碼打包成一個app/exe


前言

  打包的代碼通常都需要寫一個簡單的界面,一般用 PyQt 來寫。用 PyQt 寫界面的方法請戳這里:PyQt5的安裝及基本配置    PyQt5教程

  python提供了幾個用來打包的模塊,主要有 py2app、py2exe、pyinstaller,其中第一個是用來打包來給 mac 用的,后兩者是針對於 windows 系統。

 

關於 py2exe 和 pyinstaller 兩者的比較:

  對於 pyinstaller 和 py2exe 兩種把 Python 文件打包成 exe 可執行文件的方法,都有各自的優缺點。但是最終目的都是為了在沒有 Python 環境下的普通  Windows 系統的電腦中可直接運行。py2exe 的使用方法基本和 py2app 一樣,但是本人操作時發現在 mac 中無法用 py2exe 打包成 exe,但是可以用 pyinstaller 打包成 exe,沒有嘗試過是否可以在 windows 環境下用 py2app 打包成 app。pyinstaller (-F指令下)生成的 exe 文件,集成了所需要的所有資源(所以 exe 文件 相對較大),可直接拷貝到其他電腦中使用。對於 py2exe 來說,限制就比較多了,它所需要用到的外部資源都在 dist 目錄下,想要在其他電腦中使用就必須把整個 dist 文件夾都拷貝過去。而且經測試在 64 位機器生成的 exe 無法在 32 位機器上打開使用。

  

py2app打包

注:py2app 方法已在 Mac 環境下測試無誤,windows 環境操作時如果遇到問題請自行Google 

一、安裝py2app

sudo pip install py2app

 

二、進入要打包的文件所在的文件夾

cd 。。。。。。。。

 

三、生成setup.py文件,該文件用於寫打包所需要的依賴

py2applet   --make-setup  xxx.py  # xxx.py為項目的啟動文件,之后生成的xxx文件就是雙擊執行的app文件

執行以后目錄中會生成 setup.py 文件,用於寫入依賴的庫。

 

四、在 setup.py 文件中手動輸入需要的依賴

  如果項目很簡單,沒有導入第三方庫和自建模塊,可以忽略此步驟。

  下面是setup.py文件的一個例子,手動輸入的部分就是在 DATA_FILES 空列表里加自建模塊的名字,在 OPTIONS 字典的 includes 對應的空列表中加第三方模塊的名字

# python自帶的庫無需輸入,第三方庫和自己引入的自寫模塊需要輸入
"""
This is a setup.py script generated by py2applet

Usage:
    python setup.py py2app
"""

from setuptools import setup

APP = ['start.py']
#自寫模塊放在DATA_FILES列表中
DATA_FILES = ['xxx1.py','xxx2.py','xxx3.py']
# 第三方庫放在OPTIONS下的includes對應的列表中
OPTIONS = { 'includes': ['sip', 'PyQt5.QtCore', 'PyQt5.QtWidgets'],}

setup(
    app=APP,
    data_files=DATA_FILES,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)
示例setup.py

 

五、生成app

# 自己開發,打包速度快。(因為本機安裝了依賴庫,所以可以直接運行)
python setup.py py2app -A

# 給其他沒有 sdk 的電腦使用,包括 lib 庫。(沒有安裝 sdk 的電腦使用,需要去掉 -A,將把所有的依賴全部打包。)
python setup.py py2app 

  之后會生成 build 和 dist 兩個文件夾,啟動文件在 dist 下,雙擊就可以執行。

 

注:如果發現有問題,在重新進行上述步驟前最好先刪除 build 和 dist 兩個文件夾

rm -rf build dist

 

py2exe

  首先聲明,py2exe 在高版本的 python 環境下可能會出現不支持的情況,我在打包的時候只支持到 python3.4,不清楚目前支持到哪個 python 版本。

注:本人在 win10 下用 py2exe 打包的含有 PyQt5 寫界面的程序無法正常運行,遇到的問題很多,如果程序中用到了 PyQt5,推薦選用 pyinstaller 打包

一、安裝py2exe

pip install py2exe

 

二、進入項目目錄

cd xxxxxxxxx

 

三、在項目根目錄中自行創建setup.py文件

  該文件的作用與 py2app 的 setup.py 文件一樣,只不過需要自己手動創建,區別在於你可以任意命名該文件(如 woshinibaba.py)

 

四、在 setup.py(woshinibaba.py) 文件中寫入需要的依賴

文件中基本格式為

# -*- coding: utf-8 -*-

from distutils.core import setup
import py2exe

setup(
    # console和windows分別代表控制台和圖形界面,按需求選擇
    #console = [{"script" : 'comtrade.py'}], 
    windows = [{"script":"comtrade.py", "icon_resources": [(1, "logo.ico")]} ],
    name = 'comtrade',# 生成的exe文件名
    version = '1.0', 
    options={}, # 括號內填入的為項目所需的依賴庫和會造成報錯的文件
    data_files={})# 括號內輸入的為項目所需的依賴文件
# version ,description,name不是必須要寫的。

其他參數:

  • dist_dir           打包生成的文件放在 dist 下,可設置存放目錄(一般沒有特殊要求,可以不需修改。可使用相對路徑)
  • Compressed    默認為 0,1 為指定壓縮文件(library.zip)的行為;0 為不壓縮。
  • Zipfiles           配置共享壓縮文件的生成目錄和文件名,默認是在目錄 dist 下生成一個  “library.zip” 文件,打包了 .exe 文件運行需要的 .pyd  和 .dll 文件(不包含配置文件等)。
  • Optimize         打包優化,合法值是字符串('','O','OO')或者整型數字 (0, 1, or 2)。
    • 為 0 時:不進行優化,壓縮包大小較大,打包的編譯文件為 .pyc;
    • 為 1 時:進行少量優化,壓縮包大小略小,打包的編譯文件為 .pyo;
    • 為 2 時:優化級別最高,壓縮包大小也明顯變小,打包的編譯文件為 .pyo。
  • Bundle_files     打包綁定,64位不支持此屬性。
    • 為 0 時:pyd 和 dll 文件不會被打包到 exe 文件中;
    • 為 1 時:pyd 和 dll 文件會被打包到 exe 文件中,且不能從文件系統中加載 python 模塊;
    • 為 2 時:pyd 和 dll 文件會被打包到 exe 文件中,但是可以從文件系統中加載 python 模塊。
    • 注:
      • .py:編寫的源文件。
      • .pyc:編譯過的二進制代碼文件。如果導入一個模塊,python 將創建一個 *.pyc 文件,文件內為二進制碼,這樣可以在再次導入時更容易(更快)。
      • .pyo:當優化等級 (-O) 開啟時生成的 *.pyc 文件。
      • .pyd:相當於一個 windows dll 文件。實際上 .pyd 文件就是 dll 文件,只是略有不同。
  • Date_files       文件可執行文件所需數據。在 python27 中,需要的 MSVCP90.dll 不能單獨發布,必須確保 py2exe 復制所有的三個 dll 文件和 manifest 文件到工程目錄 dist 下,並且放在一個名為 'Microsoft.VC90.CRT' 的子目錄下。
    • 參考做法為:
      from glob import glob  
      
      data_files  = [
          ("Microsoft.VC90.CRT", 
          glob(r'C:\Program Files\Microsoft Visual Studio 
          freeze_support9.0\VC\redist\x86\Microsoft.VC90.CRT\*.*'))
      ]
  • ascii               
    • 為 0 時:不包含編碼和解碼器;
    • 為 1 時則反之。
    • 假設出現 QPixmap::scaled: Pixmap is a null pixmap 問題,這是由於 PyQt 和 qt 都是默認的 png 格式的圖片,打包后,會找不到 jpg 格式的圖片,所以在打包過程中需要把 PyQt4 文件中的imageformats 文件夾下的 dll 文件導入。這是 jpg 格式的圖片需要的插件。
  • 類標識符無屬性,產生的CLSID無屬性。

typelibs

列表:需要包含的gen_py產生的typelibs

  • 多進程打包遇到的程序不正常執行問題,需要在多進程之前調用 freeze_support() 函數。經試驗,最好在函數開始執行的時候,首先調用此函數。

具體例子:

# -*- coding: utf-8 -*-

# 必須寫的倒入模塊
from distutils.core import setup
import py2exe

# 可以不用寫的部分
"""
#We need to import the glob module to search for all files.
import glob
import sys
#this allows to run it with a simple double click.
sys.argv.append('py2exe')
"""

# 項目中需要用到的第三方庫寫入includes所對應的列表中
# 項目中用不到的會造成報錯的文件放在excludes所對應的列表中,若報錯的是dll文件,放入dll_excludes所對應的列表中
# 下面是示例:
opts= {
'py2exe':{ "includes" : [ "sip", "matplotlib.backends", "matplotlib.backends.backend_tkagg",
                          "matplotlib.figure","numpy", "matplotlib.pyplot", "pylab", "six",
                          "matplotlib.backend_bases", 'scipy.special._ufuncs_cxx',
                          "scipy.integrate","scipy.integrate.quadpack","scipy.sparse.csgraph._validation"],
           "excludes" : ['_gtkagg', '_tkagg', '_agg2', '_cairo', '_cocoaagg',
                         '_fltkagg','_gtk', '_gtkcairo'],

          "dll_excludes":['libgdk-win32-2.0-0.dll','libgobject-2.0-0.dll',"MSVCP90.dll",]
         }
      }

#項目中需要用到的外部文件依賴放入列表中,格式為[(),(),()]
# 元祖中第一個元素是打包時要創建的文件夾名,如果要放在exe文件的同目錄下就用"",第二個元素是該依賴文件的路徑
data_files= [(r'mpl-data',glob.glob(r'C:\Anaconda3\Lib\site-packages\matplotlib\mpl-data\*.*')),
            #Because matplotlibrc does not have an extension, glob does not findit (at least I think that's why)
            #So add it manually here:
            (r'mpl-data',[r'C:\Anaconda3\Lib\site-packages\matplotlib\mpl-data\matplotlibrc']),
            (r'mpl-data\images',glob.glob(r'C:\Anaconda3\Lib\site-packages\matplotlib\mpl-data\images\*.*')),
            (r'mpl-data\stylelib',glob.glob(r'C:\Anaconda3\Lib\site-packages\matplotlib\mpl-data\stylelib\*.*')),
            (r'mpl-data\fonts',glob.glob(r'C:\Anaconda3\Lib\site-packages\matplotlib\mpl-data\fonts\*.*')),
            ("",[r"C:\Anaconda3\Lib\site-packages\PyQt5\libEGL.dll"]),
            ("platforms",[r"C:\Anaconda3\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll"])]

# 將上述參數傳入setup中,console和windows分別代表控制台和圖形界面,按需求選擇
setup(
    #console = [{"script" : 'comtrade.py'}], 
    windows = [{"script":"comtrade.py", "icon_resources": [(1, "logo.ico")]} ],
    name = 'comtrade',
    version = '1.0', 
    options=opts, data_files=data_files)
setup.py(woshinibaba.py)

 

五、生成exe 

python setup.py app2exe

執行完畢后會生成build和dist文件夾,啟動文件在dist文件夾下

 

py2exe報錯解決

1. 執行打包命令時報錯 Missing run-py3.5-win-amd64.exe

  • 原因:py2exe 最高只支持到 python3.4,如果你用的 3.5 或更高的版本就會出現這個問題
  • 解決方法:創建個虛擬環境安裝 python3.4,然后 pip install 所有項目需要的第三方庫后重新進行一邊打包操作

 

2. 執行打包命令時報錯 indexError: tuple index out of range

  • 原因:py2exe 最高只支持到 python3.4,如果用更高的版本就會出現這個問題
  • 解決方法:創建個虛擬環境安裝 python3.4,然后 pip install 所有項目需要的第三方庫后重新進行一邊打包操作

3. 執行打包操作時報錯 (忘了具體報錯信息,意思時遞歸深度超過最大限制)

  • 原因:py2ex e最高只支持到 python3.4,如果你用的更高的版本就會出現這個問題
  • 解決方法:創建個虛擬環境安裝 python3.4,然后 pip install 所有項目需要的第三方庫后重新進行一邊打包操作

 

4. 打包 ok,但雙擊可執行文件時報錯 Failed to execute script xxx

  • 原因:去 log 文件中查看,會發現報錯信息為 no module named xxx,意思為項目中缺少 xxx 模塊
  • 解決方法:pip install ,如果你確定你已經安裝了該模塊,那就在 setup.py(woshinibaba.py)文件最上面 import 該模塊

 

5. 打包 ok,但雙擊可執行文件時彈窗報錯 This application failed to start because it could not find or load the Qt platform plugin "windows".

注:這是我遇到的一個最大的問題,問題原因和 PyQt5 有關目前尚未找到解決方案,然后選用了 pyinstaller

  • 疑似原因一:python3.4 不支持 PyQt5
  • 本人理解:python3.4 環境下用 pip install PyQt5,報錯說找不到該模塊,但是可以運行 pip install pyqt,而 pyqt 指得是 PyQt4,兩者是不一樣的。在 pycharm 中將其升級為 PyQt5,驚奇的發現我的python 環境變成 python3.7了?!在升級 pyqt 的同時將我的 python 都升級了?但是 py2exe 不支持 python3.7 啊,WTF?!最后本人不了了之選擇了pyinstaller

 

  • 疑似原因二:沒有將 PyQt5 寫入環境變量
  • 網上提供的解決方法一:將 QT 的 bin 目錄下的 \platforms\qwindows.dll 拷貝至 exe 所在目錄,注意保留 \platforms 子目錄
  • 網上提供的解決方法二:在 data_files 參數中加入兩個元祖,元祖中寫入(該方法與上面的方法一個作用,他會在你執行打包命令時自動將將 QT 的 bin 目錄下的 \platforms\qwindows.dll 拷貝至 exe 所在目錄)
# 注:路徑為你的python的PyQt5的路徑
data_files=[("",
            [r"F:\Python\python3\Lib\site-packages\PyQt5\libEGL.dll"]),
            ("platforms",
            [r"F:\Python\python3\Lib\site-packages\PyQt5\plugins\platforms\qwindows.dll"])]
  • 網上提供的解決方法三:改變系統變量(變量值為你的 python 所在的目錄下的 PyQt5 的目錄)

                    

 

  

 

pyinstaller

  首先要聲明,pyinstaller 在高版本的 python 環境下可能會出現不支持的情況,我在打包的時候只支持到 python3.5,不清楚目前支持到哪個 python 版本。如果你的 python 已是3.5以上的版本,建議創建一個虛擬環境后安裝 python3.5,再自行安裝上程序所依賴的庫比如 requests 等等,在新環境中進行打包。

注:pyinstaller 方法已在 win10、win8 和 Mac環境下測試無誤,但打包程序本身會因為你的程序的不同而需要有些許改動,文章末尾會有一些我遇到過的報錯的解決方法,出現問題可自行Google

一、安裝pyinstaller

pip install pyinstaller

 

二、切換到工作目錄

cd xxxxxxxxxxx

 

三、打包命令

  與上面兩個不同的是,pyinstaller 不需要自己寫 setup.py 文件,只需要在工作目錄中輸入打包命令即可。最后會生成 build 和 dist 文件夾,啟動文件在 dist 文件夾下。

命令格式:

pyinstaller [項目啟動文件]

其他參數(按需求選擇):

  • -F   表示在 dist 文件夾下只生成單個可執行文件(內部包含所有依賴),不加默認會在 dist 生成一大堆依賴文件+可執行文件。
  • -D   與 -F 相反用法
  • -W  表示去掉控制台窗口,如果你的程序是有界面的,可以不寫這個參數。但是測試情況下建議先加上這個參數,因為如果打包不成功,運行時報錯信息會在控制台上輸出,沒有控制台就看不到報錯信息。
  • -c   表示去掉窗框,使用控制台
  • -p    表示自己定義需要加載的類路徑,項目中包含多個自建模塊的時候需要加上 -p aaa.py -p bbb.py -p ccc.py
  • -i     表示可執行文件的圖標,后面跟圖標的路徑
  • --hidden-import  后面跟模塊名如 queue,用於告訴打包程序某個模塊我用不着你不用打包進去

  打包完畢后在 dist 文件夾下雙擊項目啟動文件就可以了

 

pyinstaller報錯解決

1.執行打包命令時報錯  IndexError: tuple index out of range

  • 原因:官網目前的版本是 3.2.1 只支持到 python3.5 ,高版本的 python 尚不支持,
  • 解決方法:網上有大神提供了完善版的代碼——官網源碼里有 https://github.com/pyinstaller/pyinstaller 替換你 python 目錄下的 \Lib\site-packages\PyInstaller 即可 這樣就支持python3.6了 不過是開發版,可能還不完善。

  作者建議最好還是用虛擬環境下的 python3.5 進行打包。


 

2.執行打包命令時報錯 ImportError: No module named 'queue'

  • 原因:尚不清楚
  • 解決方法:如果該模塊你用不到,可以在執行打包命令時用 --hidden-import 不打包進去。如果程序中需要該模塊,在主文件最上面寫上 improt queue

 

3.打包命令執行成功,但雙擊可執行程序彈出報錯窗口failed to excute script xxx

  • 原因:打包時內部缺少了某個依賴,這時需要看看控制台打印了什么報錯信息,打包時加了 -w 參數的請再打包一次記得去掉 -w
  • 現象:基本都是在控制台上發現報錯 No module named 'xxxxx',如 No module named 'queue' 或者 ModuleNotFoundError: No module named 'PyQt5.sip'
  • 解決方法:同2,如果該模塊你用不到,可以在執行打包命令時用 --hidden-import 不打包進去。如果程序中需要該模塊,在主文件最上面寫上 improt xxxxx。如 import queue 或 import PyQt5.sip

 

 

 

                


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM