最近準備要把手邊用 python 做的小工具交給別人使用,如果可以直接給 code 是最簡單的,但有執行上的難度,所以用 PyInstaller 包成一個執行檔,避免一些安裝、環境、dependency 等等的問題,但 script 裡有用到 cx_Oracle,所以打包的方式有點不同,筆記一下。
目前 PyInstaller 3.5 用在 python 3.8 上好像有點問題,所以本機上的 python 裝的是 3.7.5。事前安裝 Oracle Instant Client 和 cx_Oracle 的部份可以參考 cx_Oracle 的安裝說明,不過我裝了文件裡提的 Visual Studio redistributable 還是沒辦法裝 cx_Oracle,最後是另外安裝 Build Tools for Visual Studio 2019 才行,詳見前篇。
一般要打包成單一一個可執行檔是用 -F
參數:
pyinstaller -F the_script.py
此時除了包好的 exe 檔在 dist/
下外,還會有另一個 .spec
檔。修改 spec 文件,把 Oracle Instant Client 的 dll 檔加進去。
exe
區段裡的 a.binaries
要改成 a.binaries+[('oraociei19.dll','oraociei19.dll','BINARY')],
其中 oraociei19.dll
依據使用的 Oracle Instant Client 版本而定,以我的例子裝的是 v19。
改好的 spec 檔大概會長這樣:
# -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis(['check-pcu-cr-status.py'], pathex=['C:\\Users\\Administrator\\Documents\\linebot'], binaries=[], datas=[], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries+[('oraociei19.dll','oraociei19.dll','BINARY')], a.zipfiles, a.datas, [], name='check-pcu-cr-status', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=False )
將 oraociei19.dll
檔 copy 到 script 所在目錄,接著執行 pyinstaller -F the_script.spec
即可。
參考:Pyinstaller: cx_Oracle.InterfaceError: Unable to acquire Oracle environment handle