1、申 请 I D:老鼠爱小米
2、个人邮箱:u9team@foxmail.com
3、原创技术文章:Python使用Nuitka打包 加upx压缩实现软件加密分发
对比pyinstaller优点,pyinstaller打包后有些模块会缺少动态链接库或模块未引入错误等,而Nuitka直接转c编译,可避免这些问题。
为啥要单独配置一个py文件打包,命令行打包调参麻烦,而配置好Nuitka后想打包新文件只需要简单调整,运行该python文件即可完成打包。
1、Nuitka介绍:
Nuitka 是用 Python 编写的优化 Python 编译器,可创建无需单独安装程序即可运行的可执行文件。数据文件可以包含在内或放在一起。将 Python 模块转换为 C 级程序,然后使用 libpython和自己的静态 C 文件以与 CPython 相同的方式执行。安装nuitka可直接使用pip install nuitka安装最新版,打包程序使用版本为2.4.8
2、先贴程序
build.py
# -*- coding: utf-8 -*-
import os
import time
args = [
'nuitka',
'--standalone',
#'--windows-console-mode=disable', # hide console,注释掉则默认开启cmd窗口
'--plugin-enable=upx',
'--upx-binary=upx.exe',
'--msvc=latest',
'--show-memory',
'--show-progress',
'--windows-icon-from-ico=app/resource/images/logo.png',
'--include-package=aiohttp,loguru,aiosqlite,httpx,telethon,apscheduler,qasync', #包含模块,如numpy
'--include-module=app', #包含模块
'--output-dir=teletool2',
'main.py',
]
print(' '.join(args))
start = time.time()
os.system(' '.join(args))
print("打包完成,耗时:{}分".format(int(time.time() - start)/60))
导入nuitka已内置的打包模块,nuitka针对这些模块做了优化,如pyqt5,pyside6,kivy,tkinter,pywebview等。
可使用
nuitka --plugin-list
命令查看当前支持的插件列表。
多个插件使用英文逗号分隔,如:--plugin-enable=upx,pyside6
在本命令中,我们默认启动了upx来进行压缩,当带有upx命令后,需要使用--upx-binary=upx.exe来指定upx文件路径,可为项目相对路径或文件绝对路径,如关闭upx压缩,则注释或删除'--upx-binary=upx.exe'行,--plugin-enable里删除upx模块
--msvc=latest
编译器为msvc,版本为latest,此处可替换为–clang,或–mingw64,具体区别请查阅相关文档,小白建议默认即可。
--windows-icon-from-ico=app/resource/images/logo.png
win图标路径
'--include-package=aiohttp,loguru,aiosqlite,httpx,telethon,apscheduler,qasync', #包含模块,如numpy
所开发的程序中的第三方库名,可使用pip list查看引用。aiohttp,loguru,aiosqlite,httpx,telethon,apscheduler,qasync等改为你自己项目引用的第三方库,[b]--plugin-enable中添加的库此处无需再次添加
--include-module=app
为防止异常,加载项目的包文件夹进入,可多个。
'--output-dir=teletool2',
编译后程序输出文件夹
main.py项目入口文件名
使用方法:
我们这里使用pyside6的一个简单例子作为打包案例:
demo.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import random
import sys
from PySide6 import QtWidgets, QtCore
class MyWidget(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.hello = ["Hallo Welt", "Hei maailma", "Hola Mundo", "巴拉巴拉"]
self.button = QtWidgets.QPushButton("Click me!")
self.text = QtWidgets.QLabel("Hello World",
alignment = QtCore.Qt.AlignCenter)
self.layout = QtWidgets.QVBoxLayout(self)
self.layout.addWidget(self.text)
self.layout.addWidget(self.button)
self.button.clicked.connect(self.magic)
@QtCore.Slot()
def magic(self):
self.text.setText(random.choice(self.hello))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = MyWidget()
widget.resize(800, 600)
widget.show()
sys.exit(app.exec())
可以看到,此程序第三方模块只引入pyside6,修改打包文件
build.py
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import time
args = [
'nuitka',
'--standalone',
#'--windows-console-mode=disable', # hide console,注释掉则默认开启cmd窗口
'--plugin-enable=pyside6,upx',
r'--upx-binary=H:\imooc\NuitkaPackTest\upx\upx.exe',
'--msvc=latest',
'--show-memory',
'--show-progress',
'--windows-icon-from-ico=app/resource/images/telegram.png',
#'--include-package=', #包含模块,如numpy
#'--include-module=app', #包含模块
'--output-dir=build-demo',
'demo.py',
]
print(' '.join(args))
start = time.time()
os.system(' '.join(args))
print("打包完成,耗时:{}分".format(int(time.time() - start)/60))
开启命令行窗口,禁用upx压缩,导入pyside6,编译文件夹build-demo,图片**.png
修改完成后运行命令进行打包
python build.py
注意,第一次打包会要求下载缓存文件和编译器,如网络无法下载请手动下载后放到命令行所显示的文件夹位置并解压,然后再次运行编译即可。
打包完成后,在输出文件夹下demo.build和demo.dist文件夹,编译后的exe文件位于demo.dist文件夹下,运行demo.exe可看到程序效果。
编译后69M,如需缩小体积请使用upx单独压缩,或编译时开启upx自动压缩。
upx压缩后44M
upx压缩:
upx介绍:专门用于减小可执行文件的大小,从而减少磁盘占用空间和加快文件传输速度。UPX支持多种平台,包括Windows、Linux、macOS等。
第一次使用upx需要先下载编译系统对应版本:https://upx.github.io/
如需手动压缩文件:
upx -9 <filename>
UPX支持多种压缩级别,使用-1(最小压缩)到-9(最大压缩)来调整压缩比和压缩速度。默认使用-7。
如果需要单独使用upx批量压缩可使用下面这种方案。
import os
import subprocess
def compress_with_upx(directory, upx_path):
# 遍历指定目录
for root, dirs, files in os.walk(directory):
for file in files:
file_path = os.path.join(root, file)
print(f"正在压缩: {file_path}")
# 使用指定路径的 UPX 压缩文件
subprocess.run([upx_path, file_path])
# 指定 Nuitka 编译输出的目录
nuitka_output_directory = 'path/to/nuitka/output'
# 指定 UPX 可执行文件的完整路径
upx_executable_path = 'path/to/upx'
compress_with_upx(nuitka_output_directory, upx_executable_path)
注意事项:
- win编译时请关闭win安全,实时保护。也可将编译输出文件夹添加到信任目录,防止被win defender拦截写入。
- 安装pip install zstandard后再打包可以让打包出来的文件更小,只要安装zstandard就可以了,无需额外操作。
- 编译推荐使用虚拟环境或conda,使用时遇到环境错误的都推荐使用conda环境。
- 使用upx压缩时运行会比不压缩慢
- 打包为单文件运行比文件夹运行慢
- 如报错Nuitka-Plugins:WARNING: upx: No UPX binary found, please use '--upx-binary' option to specify it.请指定upx文件绝对路径
- 如修改程序后再次编译修改没生效,请禁用或删除缓存编译