[Python] Mac 使用 cx_Freeze 打包問題紀錄

本文主要記錄在 Mac 上使用 cx_Freeze 打包所遇到的各種問題與解決方案。主要所用到的套件有 opencv、easyocr、pyside6。

Overview

  1. 安裝 cx_Freeze
  2. 透過 cx_Freeze 打包
  3. 打包期間的錯誤
  4. 執行期間的錯誤
  5. M1 打包 x86 環境的問題

1. 安裝 cx_Freeze

首先透過 pip 安裝 cx_freeze

pip install cx_freeze

2. 透過 cx_Freeze 打包

接著透過 cxfreeze 打包主要的 python 程式
–target-dir:指定輸出的資料夾

cxfreeze -c <file_name.py> --target-dir <dir_name>

3. 打包期間的錯誤

FileNotFoundError: libiodbc.2.dylib

在打包過程中可能會遇到找不到這兩個 dylib 的錯誤,第一個是 libiodbc.2.dylib

FileNotFoundError: [Errno 2] No such file or directory: '/usr/local/opt/libiodbc/lib/libiodbc.2.dylib'

透過 Homebrew 來進行安裝即可

brew install libiodbc

FileNotFoundError: libpq.5.dylib

FileNotFoundError: [Errno 2] No such file or directory: '/Applications/Postgres.app/Contents/Versions/14/lib/libpq.5.dylib'

到官網下載相對應版本的 Postgres.app 拖曳到應用程式裡即可解決
官網連結:https://postgresapp.com/

4. 執行期間的錯誤:opencv + easyosr

Wrong dylib path

首先執行期可能會再遇到各種 package 找不到 dylib 的問題
但是其實都打包在輸出資料夾的根目錄下 (ex. dist)
比方說底下這個是 opencv 的:

dist/lib/cv2/.dylibs/libavcodec.58.134.100.dylib (no such file)

要解決這個問題的話,可以新增一個 command
在執行主要程式檔前,把 DYLD_LIBRARY_PATH 這個路徑指向當前路徑並 export 出來

#!/bin/bash
cd "$(dirname "$0")"
export DYLD_LIBRARY_PATH=$(pwd)
echo "$DYLD_LIBRARY_PATH"
./main

Scikit-Image:__init__.pyci

接著則是各種奇怪的的問題,不同 package 遇到的問題都不同
這個是 easyocr 所需要的 scikit-image package
透過 cxfreeze 打包後的 __init__ 副檔名為 (.pyc),把檔名改為 (.pyci) 後即可

ValueError: Cannot load imports from non-existent stub '/your_project_path/dist/lib/skimage/__init__.pyci'

SSL: CERTIFICATE_VERIFY_FAILED

再來則是遇到 SSL/TLS 憑證的問題

urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)>

這部分到以下網址下載 Mozilla 的 CA 證書
https://curl.haxx.se/docs/caextract.html

把下載好的 cacert.pem 丟到 /etc/ssl/certs/ 下
再開啟 ~/.zshrc 把路徑 export 出來

export SSL_CERT_FILE=/etc/ssl/certs/cacert.pem

Easyocr:ModuleNotFoundError:easyocr.model.model

最後則是 easyocr 打包時又漏掉檔案的錯誤

ModuleNotFoundError: No module named 'easyocr.model.model'

我們可以透過以下指令找出原本 easyocr 的 location
easyocr/model/model.py 複製到打包完的 easyocr 下即可

pip show easyocr

# Name: easyocr
# Version: 1.6.2
# ...
# Location: /Users/UserName/.pyenv-i386/versions/3.9.15/lib/python3.9/site-packages
# Requires: ninja, numpy, opencv-python-headless, Pillow, pyclipper, python-bidi, PyYAML, scikit-image, scipy, Shapely, torch, torchvision

5. M1 打包 x86 的問題

首先需要在 M1 建置 Rosetta x86 的模擬環境,詳情請見:
[Python] Mac M1 x86 環境建置

無法打開 xxx,因為 Apple 無法檢查是否包含惡意軟體

所有會用到的執行程式與動態程式庫 (dylib) 都會需要權限
我們加入一行指令到剛才提到的 execute.command 檔中,把根目錄下的檔案都新增權限
xattr -rd com.apple.quarantine $(pwd)

#!/bin/bash
cd "$(dirname "$0")"
export DYLD_LIBRARY_PATH=$(pwd)
echo "$DYLD_LIBRARY_PATH"

xattr -rd com.apple.quarantine $(pwd)

./main

發佈留言