通过nuitka将django代码进行打包

6天前学习44

在做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. 导入模块

  1. import os
  2. import subprocess
  3. import sys
  • os:用于与操作系统交互,例如设置环境变量、获取当前工作目录等。
  • subprocess:用于运行外部命令,例如调用Nuitka进行编译。
  • sys:用于访问Python解释器相关的变量和函数,例如获取当前Python解释器的路径。

2. 定义编译函数

  1. def compile_with_nuitka():

这个函数封装了使用Nuitka编译项目的逻辑。

3. 设置项目名称和输出目录

  1. project_name = "zzdata"
  2. 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. 设置环境变量

  1. os.environ["CCACHE_DIR"] = 'D:/code/ccache'
  2. os.environ["CCACHE_MAXSIZE"] = "5G"
  3. os.environ["CCACHE_TEMPDIR"] = 'D:/code/ccache/temp'
  4. os.environ["CCACHE_COMPRESS"] = "1"
  5. os.environ["CCACHE_BASEDIR"] = os.getcwd()

这些环境变量用于配置ccache,一个用于加速编译的工具:

  • CCACHE_DIR:缓存目录。
  • CCACHE_MAXSIZE:缓存的最大大小。
  • CCACHE_TEMPDIR:临时文件目录。
  • CCACHE_COMPRESS:启用压缩。
  • CCACHE_BASEDIR:基准目录,通常是当前工作目录。

6. 执行编译命令

  1. subprocess.run(cmd, check=True)
  2. print(f"\n打包完成!可执行文件位于: {os.path.abspath(output_dir)}/manage.bin")
  • subprocess.run(cmd, check=True):运行构造好的命令。check=True表示如果命令失败,会抛出异常。
  • print:打印编译完成的消息,并指出可执行文件的位置。

7. 主程序入口

  1. if __name__ == "__main__":
  2. os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings")
  3. compile_with_nuitka()
  • os.environ.setdefault("DJANGO_SETTINGS_MODULE", "application.settings"):设置Django的设置模块,确保Django项目能够正确加载配置。
  • compile_with_nuitka():调用编译函数,开始编译过程。
分享到: