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

前言

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

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

 

關於py2exe和pyinstaller二者的比較:git

  對於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位機器上打開使用。github

  

py2app打包

注:py2app方法已在Mac環境下測試無誤,windows環境操做時若是遇到問題請自行Google redis

1、安裝py2appwindows

sudo pip install py2app

 

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

cd 。。。。。。。。

 

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

py2applet   --make-setup  xxx.py#xxx.py爲你項目的啓動文件,以後生成的xxx文件就是雙擊執行的app文件

執行之後目錄中會生成setup.py文件,用於寫入依賴的庫。函數

 

4、在setup.py文件中手動輸入須要的依賴post

  若是項目很簡單,沒有導入第三方庫和自建模塊,能夠忽略此步驟。

  下面是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

 

5、生成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打包

1、安裝py2exe

pip install py2exe

 

2、進入項目目錄

cd xxxxxxxxx

 

3、在項目根目錄中自行建立setup.py文件

  該文件的做用與py2app的setup.py文件同樣,只不過須要本身手動建立,區別在於你能夠任意命名該文件(如woshinibaba.py)

 

4、在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)

 

5、生成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全部項目須要的第三方庫後從新進行一邊打包操做

 

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

  • 緣由:py2exe最高只支持到python3.4,若是你用的更高的版本就會出現這個問題
  • 解決方法:建立個虛擬環境安裝python3.4,而後pip全部項目須要的第三方庫後從新進行一邊打包操做

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

  • 緣由:py2exe最高只支持到python3.4,若是你用的更高的版本就會出現這個問題
  • 解決方法:建立個虛擬環境安裝python3.4,而後pip全部項目須要的第三方庫後從新進行一邊打包操做

 

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方法已在win十、win8和Mac環境下測試無誤,但打包程序自己會由於你的程序的不一樣而須要有些許改動,文章末尾會有一些我遇到過的報錯的解決方法,出現問題可自行Google

1、安裝pyinstaller

pip install pyinstaller

 

2、切換到工做目錄

cd xxxxxxxxxxx

 

3、打包命令

  與上面兩個不一樣的是,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
相關文章
相關標籤/搜索