使用cython+pyinstaller打包python項目


使用cython+pyinstaller打包python項目

第一步使用cython將python文件編譯成so文件,

cython 官網:

參考項目: https://github.com/cckuailong/py2sec 開箱即用

第二步安裝pyinstaller,將cyhton編譯后的項目和依賴進行打包

官網:https://www.pyinstaller.org/documentation.html

pyinstall安裝: pip install pyinstaller

pyinstaller -h 查看幫助

最簡單的使用方式:

`pyinstaller main.py``

main.py為項目的入口文件,根據具體情況修改

默認打包將所有的依賴打包到一個文件夾,如果需要修改,通過以下指令修改

-D, --onedir          打包到一個目錄 (default)
-F, --onefile       打包到一個可執行文件 

對於簡單的文件來說這已經就夠了,pyinstaller會自動搜索所有依賴,並打包依賴。

但如果你的項目里面有使用 __import__或者使用 importlib.import_module()

運行時導入的依賴,那會pyinstaller則可能不能完全導入,這里就需要幫助pyinstller找到依賴。如

--hidden-import 指令。

對於一些資源文件,如html. js等, 則可以使用—add-data添加

對於一此可執行文件,如so. dll等,則可以使用 --add-binary 來添加,注意這兩個指令的使用方式,如 --add-binary="源路徑:目標路徑" 使用;或者:分隔,取決於你在win還在linux上使用。

其它的一些指令如下

What to bundle, where to search:
  --add-data <SRC;DEST or SRC:DEST>
                        Additional non-binary files or folders to be added to the executable. The path separator is platform specific, ``os.pathsep`` (which is ``;`` on Windows and ``:`` on most unix
                        systems) is used. This option can be used multiple times.
  --add-binary <SRC;DEST or SRC:DEST>
                        Additional binary files to be added to the executable. See the ``--add-data`` option for more details. This option can be used multiple times.
  -p DIR, --paths DIR   A path to search for imports (like using PYTHONPATH). Multiple paths are allowed, separated by ``':'``, or use this option multiple times. Equivalent to supplying the ``pathex``
                        argument in the spec file.
  --hidden-import MODULENAME, --hiddenimport MODULENAME
                        
  --collect-submodules MODULENAME
                        Collect all submodules from the specified package or module. This option can be used multiple times.
  --collect-data MODULENAME, --collect-datas MODULENAME
                        Collect all data from the specified package or module. This option can be used multiple times.
  --collect-binaries MODULENAME
                        Collect all binaries from the specified package or module. This option can be used multiple times.
  --collect-all MODULENAME
                        Collect all submodules, data files, and binaries from the specified package or module. This option can be used multiple times.
  --copy-metadata PACKAGENAME
                        Copy metadata for the specified package. This option can be used multiple times.
  --recursive-copy-metadata PACKAGENAME
                        Copy metadata for the specified package and all its dependencies. This option can be used multiple times.
  --additional-hooks-dir HOOKSPATH
                        An additional path to search for hooks. This option can be used multiple times.
  --runtime-hook RUNTIME_HOOKS
                        Path to a custom runtime hook file. A runtime hook is code that is bundled with the executable and is executed before any other code or module to set up special features of the
                        runtime environment. This option can be used multiple times.
  --exclude-module EXCLUDES
                        Optional module or package (the Python name, not the path name) that will be ignored (as though it was not found). This option can be used multiple times.
												py3.9以后會把pip. 等打包進去,可以通過這個指令來排除

  --key KEY             aes加密密鑰,用於加密字節碼.
  --splash IMAGE_FILE   (EXPERIMENTAL) 添加啟動畫面

配置文件

對於配置文件打包,需要理解兩個路徑,一個路徑是程序所在的路徑,以下叫它為當前路徑,另外一個是打包的程序要運行,必須先解壓,這個解壓的路徑,以下叫它為運行時路徑。linux默認在/tmp目錄下面。

判斷當前程序的運行方式

可以通過以下代碼來檢測當前運行的程序是以打包的方式運行還是py腳本的方式運行

# ref: https://pyinstaller.readthedocs.io/en/stable/runtime-information.html
import sys
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
    print('running in a PyInstaller bundle')
else:
    print('running in a normal Python process')

路徑檢測

__file__

對於py腳本的運行方式, 這個變量指向的是py腳本的當前路徑,而對於pyinstaller打包后的程序來說。這個變量指向的是運行時路徑。

sys.executable

對於py腳本的運行方式, 這個變量指向的是python解釋器,而對於pyinstaller打包后的程序來說。這個變量指向的是當前路徑。

我們可以通過以下代碼片段得到這兩個路徑。

    weAreFrozen = True if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS') else False
    _ = sys.executable if weAreFrozen else __file__
    rootPath = os.path.dirname(os.path.realpath(_)) #當前路徑
    runtimePath = os.path.dirname(os.path.realpath(__file__))  #運行時路徑

對於配置文件來說,那我們就需要通過 os.path.join(rootPath, "myConfig")的路徑方式來訪問。

upx

可以使用upx對目標程序進行壓縮 。

先下載upx: https://github.com/upx/upx/releases

然后將upx復制到path路徑中。pyinstaller檢測到path中有upx的可執行程序時會自動調用。

如果看到以下提示,則說明正常

245 INFO: UPX is available.

示例:


pyinstaller --noconfirm  -F main.py  --key="aes密鑰" --clean  --collect-data="celpy" --add-data="./plugins/:.plugins/"   --hidden-import="xxx" --hidden-import="xxxx" 

pyi-makespec

如果程序中依賴不會變動,則可以使用pyi-makespec命令生成一個spec文件,下次則可以直接使用pyinstaller spec文件的方式來進行打包,避免每次輸入過長的命令,使用方式跟以上完全一樣,就不多寫了。


免責聲明!

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



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