python 打包exe文件

前言

python 代码由于是脚本语言,如果是需要保密的算法,最好是使用Cython将python代码编译成C语言,再使用C编译器编译,编译后难以逆向。 在Windows平台上首先使用微软的MSVC编译。考虑微软的MSVC环境体积较大,可以选择使用gcc或者clang进行编译。

使用MSVC 编译器

  1. 安装MSVC 下载vs_BuildTools.exe,然后安装,选择第一个“使用C++的桌面开发”,安装详情保持默认的勾选项,大约需要6GB左右的空间。
  2. 配置环境变量
在path中添加以下路径
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\<版本号>\bin\Hostx64\x64
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\<版本号>\include
C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Tools\MSVC\<版本号>\lib\x64
  1. 编译
# setup.py
import os
from setuptools import setup
from Cython.Build import cythonize
from setuptools import Extension

# 定义需要编译的扩展模块
extensions = [
Extension("license_manager", ["license.py"]),
Extension("main_run", ["mainrun.py"])
]

setup(
name="my_license_manager",
version="0.0.1",
ext_modules=cythonize(extensions)
)
# 编译
python setup.py build_ext --inplace
  1. 修改py导入为pyd文件
# license_manager 和上面的模块名字一样 Extension("license_manager", ["license.py"])
from license_manager import LicenseManager
  1. 打包

使用--add-binary指定上面编译输出的pyd文件,使用--add-data指定资源文件,使用--hidden-import隐藏依赖包,静态资源放在res文件夹下,打包到res目录下。第一个参数是原始路径,第二个参数是打包后的路径,.表示根目录。

# 打包
pyinstaller -F -w --add-data "res;res" run.py --add-binary "main_run.cp313-win_amd64.pyd;." --add-binary "license_manager.cp313-win_amd64.pyd;." --hidden-import xml --hidden-import xml.etree --hidden-import xml.etree.ElementTree --hidden-import wmi --hidden-import ctypes

注意:res目录打包到exe后,并非真正从exe中加载,而是自动解压exe中的资源文件到_MEIPASS目录,然后从_MEIPASS目录加载资源文件。所以需要注意获取资源文件的路径。

def _get_resource_path(self,relative_path: str) -> str:
"""获取资源绝对路径,兼容pyinstaller -F / -D"""
if getattr(sys, 'frozen', False):
# 打包后运行
base_path = sys._MEIPASS
else:
# 开发调试,脚本所在目录
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)

使用clang/gcc编译

  1. 安装clang/gcc

安装完MSYS2后,找到相应的命令行终端,如果使用clang环境,需要打开clang64终端操作。
注意:gcc 存在问题,即使是最简单的hello world程序,编译不报错,也没有任何输出文件。开始以为是代码文件或者安装环境问题,github上有多人反映相同的问题,好像自从版本14之后就存在此问题,现在都到16了,问题依然存在。

# gcc
pacman -S mingw-w64-x86_64-toolchain
# clang
pacman -S mingw-w64-clang-x86_64-toolchain
  1. 安装python包 MSYS2中的python和系统的python包不同,不能混用,在MSYS2环境需要重新安装。并且需使用pacman安装,而不能使用pip安装。 例如安装 setuptools
pacman -S mingw-w64-clang-x86_64-setuptools
pacman -Ss 关键词 # 搜索包名
  1. 打包 经验证,使用clang编译打包可以在Windows上运行。最先使用的clang编译打包,打包后提示不是有效的32位程序,怀疑是clang的问题,后改为MSVC编译打包,还是提示不是有效的32位程序。最终发现是由于静态资源的路径导致的问题。解决路径问题后,两种方式打包均可以正常运行,使用MSVC编译打包的exe文件体积更小。