python应用打包分发纪要

news/2024/5/19 21:31:35 标签: python, pyinstaller, nuitka

农夫山泉,喝起来有点甜;python应用,运行起来有点慢。但,除了慢,它就别无缺点了。

文章目录

前言

只有打包,才方便分发,才能流传后世。故此,颇有研究必要。
PyQt + pyinstaller成为一些中小项目界面包装和软件分发的优良选择。多快好省,省去很多烦恼。
打包主要是收集依赖,其次是形成正确的目录结构,最后才是包装成平台需要的可执行程序。

打包工具:PyInstaller,nuitka,cx_Freeze,PyOxidizer,PyInstaller-Qt,PyInstaller-PySide,Py2exe
首选pyinstaller,此选nuitkapyinstaller打包速度快,但nuitka打包后的程序运行更快,代码更难被破解。nuitka打包会遇到各种问题。

Python程序分发思考

  1. pyinstaller 打包, – 需要各平台单独打包。有反编译风险。
  2. 用 Cython 将 py 编译成 .pyd/.so ->在用 pyinstaller 进行打包 。 – 各平台单独打包分发、反编风险小
  3. pyarmor 是一个专业混淆代码库,也是编译成字节码然后用-> pyinstaller 打包分发 ---- 各平台单独打包分发、反编风最小
  4. Nuitka 直接使用 Clang 进行编译运行。

pyc文件: Python源代码import后,编译生成的字节码,类似于java的class文件。例如__pycache__ 目录用于存放pyc

PYD 文件是用Python 编写的动态链接库,可以在运行时由其他Python 代码运行。 它包含一个或多个Python 模块,便于代码重用,并为编写应用程序提供模块架构。pyd库可以被python调用,也可以被C或其它程序调用。ctypes.cdll.LoadLibrary()用于加载pyd文件。

Cython

cythonize可以将py文件编译成pyd。

pip install Cython
cythonize -i -3 --directive always_allow_keywords=true xxx.py

python中调用pyd:

python">import ctypes

# 加载 Pyd 文件
mylib = ctypes.cdll.LoadLibrary('mylib.pyd')

# 调用 Pyd 文件中的函数
result = mylib.add(1, 2)

# 打印结果
print(result)

pyinstaller_45">pyinstaller

pyinstaller options script.spec

当通过spec文件来生成app文件的时候只有下面几个参数是有用的:

  • –upx-dir=
  • –distpath=
  • -noconfirm=
  • –ascii

nuitka_57">nuitka

Nuitka提供了一个激进的解决方案。它将Python程序编译为C语言二进制文件——不是通过将CPython运行时与程序字节码打包,而是通过将Python指令翻译成C语言。其结果能够以压缩包的形式分发,也可以与其他第三方产品一起打包到安装程序中。Nuitka还试图保持与Python生态系统的最大兼容性,因此NumPy等第三方库可以可靠地工作。Nuitka还尽可能地对编译后的Python程序进行性能改进,但同样不会牺牲整体兼容性。

ccache

ccache(“compiler cache”的缩写)是一个编译器缓存,该工具会高速缓存编译生成的信息,并在编译的特定部分使用高速缓存的信息, 比如头文件,这样就节省了通常使用 cpp 解析这些信息所需要的时间。如果某头文件中包含对其他头文件的引用,ccache会用那个文件的 cpp-parsed版本来取代include声明,不是真正去读取、理解并解释其内容,ccache 只是将最终的文本拷贝到文件中,使得它可以立即被编译。ccache是以空间换取速度,ccache非常适合经常make clean(或删除out目录)后重新编译的情况。

nuitka_62">nuitka打包原理

nuitka打包过程,就是一个将引用的库打包成pyd的过程。根据py文件中from、import遍历相应模块文件打包到打包程序中,一旦遇到pyd,则不再递归查找下一层模块py文件。

nuitka_64">nuitka主要参数

  • –nofollow-imports, 所有的import全部不使用,交给python3x.dll/libpython3.11.dylib执行
  • –follow-imports, 仅遵循通过import语句在代码中显式声明的导入。它不处理动态导入即importlib.import_module(‘modulename’)
  • –follow-import-to=need , need为你需要编译成C/C++的py文件夹名称,可以指定整个package,也可以是package下的某个模块
  • –include-package=mypackage : 导入某个包
  • –include-module=mypackage.mymodule : 导入包中某个模块

注意:推荐使用python完整安装的版本,不要使用pyenv安装的,否则面临一堆的编译问题。

python -m nuitka \
          --standalone \
          --onefile\
          --enable-plugin=pyqt5\
          --macos-create-app-bundle\
          --output-dir=build\
          --assume-yes-for-download\
          --macos-app-version=2.0\
          --disable-console\
          --include-data-dir=PyQt5/Qt5=PyQt5/Qt5  \
          calculator.py

或:

python">python3 -m nuitka --follow-imports --enable-plugin=pyside6 --standalone main.py

打包PyQt5应用:

~/anaconda3/bin/python -m nuitka --recurse-all --recurse-directory=./ main.py

示例: 打包PySide6应用

mkdir pyside6nuitka
cd pyside6nuitka/
python3 -m venv env

source env/bin/activate
pip install nuitka
pip install pyside6

pip list
Package    Version
---------- --------
Nuitka     0.6.16.2
pip        20.2.3
PySide6    6.1.2
setuptools 49.2.1
shiboken6  6.1.2

写一个简单的应用:

python">import sys
from PySide6.QtWidgets import QApplication
from PySide6.QtWidgets import QMainWindow
from PySide6.QtGui import QScreen

app = QApplication(sys.argv)
mainwindow = QMainWindow()
mainwindow.setGeometry(0, 0, 800, 600)
mainwindow.show()

app.exec()

打包:

python3 -m nuitka --follow-imports --enable-plugin=pyside6 --standalone main.py
Nuitka will make use of ccache to speed up repeated compilation.
Is it OK to download and put it in '/Users/loek/Library/Application Support/Nuitka/ccache/v4.2.1'.
No installer needed, cached, one time question.
Proceed and download? [Yes]/No

选No,然后:

Nuitka:INFO: Successfully created 'main.dist/main'.

执行:main.dist/main
发现报错:

ImportError: dlopen(../dev/pyside6nuitka/./main.dist/PySide6/QtWidgets.so, 2): Library not loaded: @rpath/QtQml.framework/Versions/A/QtQml
Referenced from: ..dev/pyside6nuitka/main.dist/libpyside6.abi3.6.1.dylib
Reason: image not found

在这里插入图片描述进入main.dist/PySide6,将venv环境中的pyside6nuitka/env/lib/python3.9/site-packages/PySide6/拷到main.dist/PySide6下即可。
在这里插入图片描述再运行就正常了。

参考链接

  • PyOxidizer
  • Nuitka: Nuitka is a Python compiler written in Python.
  • py2exe
  • py2app

http://www.niftyadmin.cn/n/5442604.html

相关文章

数据库迁移测试

数据库 数据源变更:数据库名称、数据库类型等,一般情况下在同类型的数据库之间迁移比较常见,但是也存在不同类型的数据库之间的迁移,例如:oracle到MySQL等等,非关系型数据库到关系型,关系型到非…

STM32CubeMX+freeRTOS+事件组 多任务处理LED和串口打印

摘要:利用CubeMx配置freeeRTOS建立任务并使用事件组实现按键按下时 LED开关和打印信息到串口,上位机接收显示。 验证STM32CubeMx配置的FreeRTOS的任务和事件组使用 方案:按下Key1,绿灯亮或者灭,同时串口打印Key1被按下了到上位机;相关端口和串口配置省略。 新建三个任务…

Linux手动创建用户不使用useradd【七步走完成】

文章目录 第一步:修改 /etc/passwd 文件第二步:修改 /etc/shadow 文件第三步:修改 /etc/group 文件第四步:新建用户家目录第五步:复制/etc/skel目录下的环境变量配置文件到家目录下第六步:修改家目录的权限…

伊理威科技:抖音店铺运营好做吗

在数字营销的浪潮中,抖音以其强大的用户基础和独特的算法推荐机制成为了众多商家眼中的“香饽饽”。然而,对于许多初涉此领域的商家来说,心中不免有这样的疑问:“抖音店铺运营好做吗?” 运营一个抖音店铺并非易事。它既需要创意的…

org.springframework.beans.factory.BeanNotOfRequiredTypeException异常处理

目录 一、问题详情 二、示例代码 三、原因分析 四、解决方案 一、问题详情 在本地启动项目的时候,突然报了如下错误,导致整个项目启动失败了。 org.springframework.bea

java 重载和重写的区别

在开始说它们之间的区别之前,可以先去了解这两个是什么? 重载可参考链接 java方法重载-CSDN博客 重写可参考链接 java 方法重写-CSDN博客 1、方法重载 (1)方法在同一个类中; (2)方法的名字必…

从零开始学习typescript系列5: typescript特殊符号之感叹号、问号、双问号

感叹号 感叹号:强制链式调用 表示:这个字段一定要存在实际:如果不存在 》 会运行时报错 function logFun(p: any): void {// 真实情况: p.fruite是存在的console.log(fruit name:, p.fruit!.name); // fruit name: banana// 真实情况: p是…

spring boot唯一性判断不满足后,如何Transactional回滚

在Spring Boot中,如果需要在唯一性判断不满足时进行事务回滚,可以通过以下方式实现: 首先,确保你的方法添加了Transactional注解,这会使得该方法在一个数据库事务中执行,如果方法中出现任何异常&#xff0…