通过nuitka将django代码进行打包
在做python项目的时候最怕的就是写好的代码其他人拿到就能运行,为了代码不被别人查看,最开始想到的是代码加密。代码加密也存在被破解的风险,而且别人还是可以看到目录结构。后来想的看能不能将代码打包成二进制文件,不能被反编译或被逆向工程的。
在网上搜了下,找到一个新的打包库,nuitka。他可以将代码编译成C,然后打包成二进制文件,就算被反编译,也是C代码,想跑起来也不容易。
nuitka的命令特别多,还是依托AI才最终搞定。
以下是打包django的示例代码。
一、只打包编写大代码,不包含python环境
import os
import subprocess
import sys
import shutil
import time
def compile_with_nuitka():
project_name = "zzdata"
output_dir = "dist"
cmd = [
sys.executable, "-m", "nuitka",
"--module", # 编译为 Python 模块
"--nofollow-imports", # 不自动跟随导入
"--include-package=application", # 包含项目主包
"--include-package=publicapp",
"--include-package=until",
f"--output-dir={output_dir}",
"--show-progress",
"--show-memory",
"--remove-output", # 清理中间文件
"--enable-plugin=multiprocessing", # 启用多进程支持
"--python-flag=-OO", # 优化字节码
"--lto=yes", # 链接时优化
"--jobs=0", # 多线程编译
"application", # 编译项目主包
]
# 执行 Nuitka 编译
subprocess.run(cmd, check=True)
# 手动复制 manage.py 到输出目录
shutil.copy2("manage.py", os.path.join(output_dir, "manage.py"))
print(f"\n打包完成!编译后的模块位于: {os.path.abspath(output_dir)}")
print("使用 python manage.py runserver 启动应用")
if __name__ == "__main__":
# 使用clcache加速编译
os.environ["CCACHE_DIR"] = 'D:/code/ccache'
os.environ["CCACHE_MAXSIZE"] = "5G"
os.environ["CCACHE_TEMPDIR"] = 'D:/code/ccache/temp'
os.environ["CCACHE_COMPRESS"] = "1"
os.environ["CCACHE_BASEDIR"] = os.getcwd()
start_time = time.time() # 获取开始时间
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
compile_with_nuitka()
end_time = time.time() # 获取结束时间
print("打包用时:", end_time - start_time, "秒")
以上代码打包后的目录结构如下
在python环境里面运行以下命令启动
python manage.py runserver
可以正常启动django
2、带python环境的打包,打包为exe文件
import os
import subprocess
import sys
def compile_with_nuitka():
project_name = "zzdata"
output_dir = "dist"
cmd = [
sys.executable, "-m", "nuitka",
"--standalone",
# "--onefile",
"--follow-imports",
"--nofollow-import-to=*.tests,*.test,unittest,pytest",
"--include-package=django",
"--include-package=py2neo",
"--include-module=py2neo.data",
"--include-module=py2neo.database",
"--include-package=py2neo.integration",
"--include-package=py2neo.movies",
"--include-package=urllib3",
"--include-package=pygments",
"--include-package=pytz",
"--include-package=click",
"--include-package=colorama",
"--include-package=application",
"--include-package=labelapp",
"--include-package=dataapp",
"--include-package=indexapp",
"--include-package=publicapp",
"--include-package=newlableapp",
"--include-package-data=django.contrib.admin",
"--include-data-dir=static=static",
"--include-data-file=manage.py=manage.py",
"--include-module=psycopg2",
"--include-module=django.db.backends.postgresql",
f"--output-dir={output_dir}",
"--remove-output",
"--enable-plugin=multiprocessing",
"--python-flag=-OO",
"--lto=no",
"--assume-yes-for-downloads",
"--show-progress",
"--show-memory",
"manage.py",
]
# 如果不需要控制台窗口,可以添加以下选项
# if sys.platform == "win32":
# cmd.append("--windows-disable-console")
# 使用clcache加速编译
os.environ["CCACHE_DIR"] = 'D:/code/ccache'
os.environ["CCACHE_MAXSIZE"] = "5G"
os.environ["CCACHE_TEMPDIR"] = 'D:/code/ccache/temp'
os.environ["CCACHE_COMPRESS"] = "1"
os.environ["CCACHE_BASEDIR"] = os.getcwd()
# 执行编译命令
subprocess.run(cmd, check=True)
print(f"\n打包完成!可执行文件位于: {os.path.abspath(output_dir)}/manage.bin")
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
compile_with_nuitka()
代码解析
1. 导入模块
- import os
- import subprocess
- import sys
- os:用于与操作系统交互,例如设置环境变量、获取当前工作目录等。
- subprocess:用于运行外部命令,例如调用Nuitka进行编译。
- sys:用于访问Python解释器相关的变量和函数,例如获取当前Python解释器的路径。
2. 定义编译函数
- def compile_with_nuitka():
这个函数封装了使用Nuitka编译项目的逻辑。
3. 设置项目名称和输出目录
- project_name = "zzdata"
- output_dir = "dist"
- project_name:项目名称,虽然在代码中没有直接使用,但可能是用于标识项目。
- output_dir:编译后的输出目录,设置为dist。
4. 构造Nuitka编译命令
- sys.executable:获取当前Python解释器的路径,确保使用的是正确的Python环境。
- -m nuitka:调用Nuitka模块。
- --standalone:生成独立的可执行文件,包含所有依赖。
- --follow-imports:自动跟踪所有导入的模块,确保它们都被包含在可执行文件中。
- --nofollow-import-to:排除某些模块,避免不必要的依赖被包含。
- --include-package 和 --include-module:显式包含某些包或模块,确保它们在编译时被包含。
- --include-package-data 和 --include-data-dir:包含某些包的数据文件。
- --output-dir:指定输出目录。
- --remove-output:在编译完成后删除中间文件。
- --enable-plugin=multiprocessing:启用多进程插件。
- --python-flag=-OO:设置Python优化级别为-OO,这会移除__doc__等属性。
- --lto=no:禁用链接时优化(Link Time Optimization)。
- --assume-yes-for-downloads:自动接受所有下载提示。
- --show-progress 和 --show-memory:显示编译进度和内存使用情况。
- manage.py:指定要编译的入口文件。
5. 设置环境变量
- os.environ["CCACHE_DIR"] = 'D:/code/ccache'
- os.environ["CCACHE_MAXSIZE"] = "5G"
- os.environ["CCACHE_TEMPDIR"] = 'D:/code/ccache/temp'
- os.environ["CCACHE_COMPRESS"] = "1"
- os.environ["CCACHE_BASEDIR"] = os.getcwd()
这些环境变量用于配置ccache,一个用于加速编译的工具:
- CCACHE_DIR:缓存目录。
- CCACHE_MAXSIZE:缓存的最大大小。
- CCACHE_TEMPDIR:临时文件目录。
- CCACHE_COMPRESS:启用压缩。
- CCACHE_BASEDIR:基准目录,通常是当前工作目录。
6. 执行编译命令
- subprocess.run(cmd, check=True)
- print(f"\n打包完成!可执行文件位于: {os.path.abspath(output_dir)}/manage.bin")
- subprocess.run(cmd, check=True):运行构造好的命令。check=True表示如果命令失败,会抛出异常。
- print:打印编译完成的消息,并指出可执行文件的位置。
7. 主程序入口
- if __name__ == "__main__":
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
- compile_with_nuitka()
- os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings"):设置Django的设置模块,确保Django项目能够正确加载配置。
- compile_with_nuitka():调用编译函数,开始编译过程。