天天看點

[python學習筆記] py2exe 打包

遇坑

之前經過折騰,pyinstaller打封包件可以在别的windows7上運作。但是,mfk, 客戶說是xp系統。崩潰

使用pyinstaller各種折騰,打包出來的依然是不是有效的win32程式,各種報錯。

後來嘗試使用 py2exe 打包

使用

  • 安裝 不廢話,下載下傳exe版,傻瓜式安裝
  • 使用
    • 編寫類似一個 setup.py 檔案,寫各種配置(下邊有)
    • 調用指令
    python setup.py py2exe
               
    • 或者在setup.py下添加如下語句,點選檔案自動運作
    sys.argv.append('py2exe')
               
    • 官方示例: http://www.py2exe.org/index.cgi/Tutorial
    • 具體參數含義見:http://www.py2exe.org/index.cgi/ListOfOptions

問題

  • 不是有效的win32程式

    換32位的python,其他子產品都重裝,包括pyqt5

  • py2exe UnicodeDecodeError: 'gbk' codec can't decode

    py2exe 的runtime.py 裡 打開檔案制定為utf-8

    with open(target.script, "U",encoding="UTF-8") as script_file:

  • 編譯PyQt5 異常

    把一句 Exception, e 該為 Exception as e 就好了

  • could not find or load the Qt platform plugin "windows"

    把 C:\Python34\Lib\site-packages\PyQt5\plugins 下的 platforms 拷貝到 打包目錄下的platforms搞定

  • 找不到 msvc**100.dll 問題

    把system32 目錄下的 msvc**.dll 的三個dll檔案拷貝到打包目錄下

分享一下完成的打包腳本

from distutils.core import setup
import py2exe
import sys
import os
import glob
import shutil
import msvcrt



#this allows to run it with a simple double click.
sys.argv.append('py2exe')
PYTHON_HOME = os.getenv('PYTHON_HOME')
TARGET_DIR = '../build2'

# 删除原來生成的路徑
if os.path.exists(TARGET_DIR):
  print("是否删除檔案夾(y/n)\t" + os.path.abspath(TARGET_DIR))
  d = msvcrt.getch()
  if d == b'y':
    shutil.rmtree(TARGET_DIR)
    print(os.path.abspath(TARGET_DIR)+'  被删除')



def find_data_files(dlist,source,target,patterns):
    # 是否有特殊符号
    if glob.has_magic(source) or glob.has_magic(target):
        raise ValueError("Magic not allowed in src, target")
    ret = dlist
    for pattern in patterns:
        # 給pattern 上添加目錄
        pattern = os.path.join(source,pattern)
        # 通過pattern尋找滿足條件的檔案
        for filename in glob.glob(pattern):
            # 判斷檔案是否存在
            if os.path.isfile(filename):
                # 擷取相對source 的相對路徑
                relP = os.path.relpath(filename,source)
                # 設定為目标路徑
                targetpath = os.path.join(target,relP)
                # 擷取目标檔案的檔案夾
                path = os.path.dirname(targetpath)
                ret.setdefault(path,[]).append(filename) 
print('-------------------')
print('資源拷貝')
data_files = {}
# 拷貝xp需要的msvc**100.dll
find_data_files(data_files,'C:/Windows/System32/','',['msvc*100.dll'])
# 拷貝pyqt5裡依賴的dll
find_data_files(data_files, PYTHON_HOME+'/Lib/site-packages/PyQt5/plugins/platforms','platforms',['*.dll'])
# 把目前目錄下ui檔案夾内容拷貝到目标檔案夾的ui檔案夾下
find_data_files(data_files,'ui','ui',['*.*'])
# 拷貝配置檔案
find_data_files(data_files,'config/','config/',['*.*'])
# 轉成鍵值對集合
data_files = data_files.items()
print(data_files)
print('--------------------------')

OPTIONS = {
  'py2exe': {
    "includes": ["sip"],# 導入依賴 sip
    # "dll_excludes": ["MSVCP90.dll","MSVCR100.dll"],
    # 是否壓縮 1 壓縮。 0 不壓縮
    "compressed": 1,
    # 優化級别。 0 不優化 pyc 1 優化 pyd 2 pyo
    "optimize": 2,
    # 依賴的包
    "packages": ["xml.etree", "xml"],
    # 是否把dll打包到壓縮包裡
    # 1 所有的都打包  2 除了python解釋器,其他的都打包 3 所有的不打包
    "bundle_files": 1,
    # 生成的檔案夾
    'dist_dir':TARGET_DIR
  },

}
setup(
      name = '登入器',
      version = '1.0',
      # 需要生成exe檔案的 py。因為可能會有多個入口
      windows = [
        {
          'script':'Login.py',
          # 圖示前的索引依賴ico裡的圖示數
          "icon_resources":[(0, "ui/icon.ico")]
        }
      ],
      data_files = data_files,
      options = OPTIONS,
      # 預設生成一個 library.zip 用來存放打包資料。如果設定為None,則打包資料存放在exe檔案裡
      zipfile = None,
)
print("打包結束,按任意鍵退出..") 
msvcrt.getch()
           

轉載于:https://www.cnblogs.com/boliu/p/7580919.html