PyApp:一种将 Python 工程打包为可执行文件的简易方法

PyApp:一种将 Python 工程打包为可执行文件的简易方法

PyApp 工具以 Rust 语言编写,可将 Python 程序封装为独立的“点击即运行”可执行文件。它或许是目前最易用的 Python 打包工具。

每个开发者都知道,要把一个 Python 程序重新分发为独立的、点击即运行的软件包是多么困难。虽然市面上有第三方解决方案,但它们都存在各种缺点。

  • PyInstaller:这是历史最悠久、也最知名的工具,但使用起来颇为棘手,往往需要大量的试错才能生成一个可用的分发包。
  • Nuitka:这是一个较新的项目,它将 Python 程序编译为可分发的二进制文件,但生成的产物体积可能非常庞大,且编译耗时很长。

而一个名为 PyApp 的新项目,采取了一种截然不同的方法。它是一个 Rust 程序,你需要结合想要分发的 Python 项目信息,从源代码进行编译。生成的结果是一个独立的二进制文件,运行时会将你的项目解压到一个目录中并从中执行。最终用户无需在他们的系统上安装 Python 即可使用它。

搭建 PyApp 环境

与其他 Python 分发解决方案不同,PyApp 既不是像 PyInstaller 那样的 Python 库,也不是一个直接接收你的程序并生成产物的独立程序。相反,你需要为每一个想要分发的 Python 程序,定制化构建一个专属的 PyApp。

在使用 PyApp 部署 Python 程序之前,你需要先搞定以下几个先决条件:

  1. PyApp 的源代码:克隆一份 PyApp 的源码,并将其放在一个独立的目录中,与其他项目隔离开。
  2. Rust 编译器及相关环境:如果你不熟悉 Rust 或其工具链,至少需要掌握如何从源代码编译一个 Rust 程序的基础知识。
  3. 打包为 Wheel 格式的 Python 程序:“Wheel”(即 .whl 文件)是用于打包 Python 程序及其平台特定组件(如预编译库)的二进制格式。如果你还没有目标程序的 wheel 包,就需要生成一个。你也可以直接使用托管在 PyPI 上的 wheel 包。

配置环境变量

PyApp 在构建过程中会读取环境变量,以确定你要编译哪个 Python 项目以及如何支持它。以下是最常用的变量:

  • PYAPP_PROJECT_NAME:定义你要打包的 Python 项目的名称。如果你使用 pyproject.toml 定义项目,它应与 project.name 属性匹配。这也可以是 PyPI 上某个项目的名称;如果不是,你就需要定义所用 .whl 文件的路径。
  • PYAPP_PROJECT_VERSION:如果需要,用它来配置项目的特定版本。
  • PYAPP_PROJECT_PATH:指向你的项目 .whl 文件的路径(相对或绝对路径)。如果你只是从 PyPI 安装 wheel 包,则可省略此变量。
  • PYAPP_EXEC_MODULE:许多 Python 包可以通过模块形式直接运行。此变量用于声明要使用的模块。例如,如果你的程序通过 python -m thisprogram 运行,就将此变量设为 thisprogram
  • PYAPP_EXEC_SPEC:针对具有入口点脚本的程序,你可以在这里指定。它对应 pyproject.toml 中 project.scripts 部分的语法。例如,pyprogram.cmd:main 会导入你程序模块中的 pyprogram.cmd,然后执行其中的 main() 函数。
  • PYAPP_EXEC_SCRIPT:此变量允许你提供一个任意 Python 脚本的路径,该脚本会被嵌入二进制文件并在启动时执行。
  • PYAPP_DISTRIBUTION_EMBED:通常情况下,当你创建 PyApp 二进制文件时,它会在首次执行时从互联网下载运行所需的 Python 发行版。如果将此变量设为 1,PyApp 会将所需的 Python 发行版预先打包进生成的二进制文件中。结果是生成的文件体积更大,但它无需下载任何内容,可以直接解压并运行。

虽然还有许多其他选项可用,但对于大多数项目而言,以上这些已经足够了。

为了方便自己,你可以为每个项目创建一个 shell 脚本,用于设置这些环境变量并运行编译过程。

构建 PyApp 二进制文件

设置好环境变量后,进入 PyApp 源码的根目录,使用 Rust 编译器运行以下命令来构建 PyApp:

cargo build --release 

这可能需要花费几分钟时间,因为 PyApp 的依赖项相当多。不过,等到 Rust 获取并缓存了所有依赖后,后续的编译过程就会快得多。

请注意:虽然理论上可以进行跨平台编译(即在一种平台上编译出适用于其他平台的程序),但这并不被推荐,也不受官方支持。

编译完成后,生成的二进制文件会位于 PyApp 项目目录下的 target/release 子文件夹中,文件名为 pyapp.exe。你可以根据需要随意重命名该文件,只要保持其可执行文件的属性即可。

运行 PyApp 二进制文件

要测试该二进制文件,只需在控制台中直接运行它。如果一切正常,你应该能看到控制台中出现提示信息,显示 PyApp 正在自我解压并准备运行。如果在控制台中看到任何报错信息,请留意这些提示并检查你的环境变量设置;很有可能是项目的入口点或启动脚本没有正确配置。

当 PyApp 二进制文件首次运行时,它会将自己解压到一个目录中,该目录通常位于用户配置文件的子目录下。在后续的运行中,它会直接使用那个已经解压好的副本,因此启动速度会快得多。

如果你希望控制二进制文件的解压位置,可以通过设置环境变量来指定程序运行时读写及查找其解压内容的目录:

PYAPP_INSTALL_DIR_<project_name> = "path/to/directory"

请注意,<project_name> 是 PYAPP_PROJECT_NAME 变量的大写版本。因此,对于名为 conwaylife 的程序,我们使用的变量名应为 PYAPP_INSTALL_DIR_CONWAYLIFE。该目录可以是绝对路径,也可以是相对路径,例如你可以使用 ./app 这样的目录,表示将程序解压到当前工作目录下的 app 子文件夹中。

另外请注意,此设置并非持久化的。如果你在运行程序时没有设置这个确切的环境变量,程序将默认解压到用户配置文件目录下。

PyApp 选项

部署好的 PyApp 可执行文件内置了几个方便的命令:

  • pyapp self remove:从解压目录中移除已解压的应用程序。
  • pyapp self restore:移除并重新安装应用程序。

再次提醒,如果你使用了 PYAPP_INSTALL_DIR_ 变量来指定项目存放位置,那么在运行上述命令时,也必须设置该环境变量!

此外,还有一点很重要:在 Microsoft Windows 系统上,PyApp 打包的应用程序可能会被杀毒软件误报(产生“假阳性”),因为生成的可执行文件默认没有进行代码签名。

Read more

Linux手搓进程池:从原理到实现,手把手教你搞定进程复用

Linux手搓进程池:从原理到实现,手把手教你搞定进程复用

🔥个人主页:Cx330🌸 ❄️个人专栏:《C语言》《LeetCode刷题集》《数据结构-初阶》《C++知识分享》 《优选算法指南-必刷经典100题》《Linux操作系统》:从入门到入魔 《Git深度解析》:版本管理实战全解 🌟心向往之行必能至 🎥Cx330🌸的简介: 目录 前言: 一、先搞懂:进程池是什么?核心优势有哪些? 二、手搓进程池:分步实现(附完整代码) 步骤1:前期准备——定义任务类型与测试任务 步骤2:实现子进程工作逻辑——任务执行的核心 步骤3:封装Channel类——管理主从进程通信与子进程 步骤4:封装ProcessPool类——进程池核心管理逻辑 步骤5:主函数测试 三、编译运行与结果分析(附Makefile) 四、完整代码展示 五、进阶优化:让进程池更实用 六、常见坑点与注意事项

By Ne0inhk
Linux进阶:玩转文件与权限管理

Linux进阶:玩转文件与权限管理

🔥 码途CQ:个人主页 ✨ 个人专栏:《Linux》 | 《经典算法题集》《C++》《QT》 ✨ 追风赶月莫停留,无芜尽处是春山! 💖 欢迎关注,一起交流学习 💖 📌 关注后可第一时间获取C++/Qt/算法干货更新 🌟 🚀 第一章:欢迎回到Linux命令行世界! 在上一篇文章中,我们一起认识了Linux的基础文件操作命令,是不是已经对那个黑乎乎的终端窗口有了些许亲切感?今天,我们将继续深入,学习更多实用指令,尤其是Linux中至关重要的文件操作和权限管理。 🎩 进阶思维:如果说基础命令是Linux的“单词”,那么今天的命令就是“语法”,而权限系统则是整个语言的“规则体系”。 一、温故知新:快速回顾 还记得这些命令吗? ls -la # 查看详细信息cd ~ # 回家mkdir -p a/b/c # 创建多层目录rm -rf danger # 危险!慎用! 很好!现在让我们进入今天的主菜。 📁 第二章:

By Ne0inhk
Flutter 组件 shelf_static 的适配 鸿蒙Harmony 实战 - 驾驭极致静态资源分发、实现鸿蒙端文件服务器缓存策略与资产审计方案

Flutter 组件 shelf_static 的适配 鸿蒙Harmony 实战 - 驾驭极致静态资源分发、实现鸿蒙端文件服务器缓存策略与资产审计方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 shelf_static 的适配 鸿蒙Harmony 实战 - 驾驭极致静态资源分发、实现鸿蒙端文件服务器缓存策略与资产审计方案 前言 在鸿蒙(OpenHarmony)生态的分布式离线静态文档系统、内嵌 H5 业务容器中台以及需要为局域网成员提供高性能资产分发的各种垂直类应用开发中,“静态资源的高速投递与安全性管控”是应用响应质量的基石。面对包含数千张高密度解析图纸、复杂的 Web 前端资产包或者是需要对接 0307 批次资产安全标准的各类文档。如果仅仅依靠原始的 File.readAsBytes() 配合手写 HTTP 头返回。那么不仅会导致在鸿蒙端产生严重的内存拷贝开销,更会因为无法实现对 Etag 缓存校验、范围请求(Range Request)等现代 Web 协议的精确支配。引发鸿蒙系统应用在加载大型资产时的严重卡顿。 我们需要一种“物理对齐、协议自洽”

By Ne0inhk
Flutter 三方库 appstream 的鸿蒙化适配指南 - 驾驭 Linux 生态元数据规范,打造高性能、标准化、国际化的 OpenHarmony 桌面应用商店分发基石

Flutter 三方库 appstream 的鸿蒙化适配指南 - 驾驭 Linux 生态元数据规范,打造高性能、标准化、国际化的 OpenHarmony 桌面应用商店分发基石

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 appstream 的鸿蒙化适配指南 - 驾驭 Linux 生态元数据规范,打造高性能、标准化、国际化的 OpenHarmony 桌面应用商店分发基石 前言 随着鸿蒙(OpenHarmony)生态向 PC 和平板端的高速扩张,如何为海量的三方软件建立一套标准化的“数字档案”,成了构建应用商店生态的核心痛点。过去,开发者提交应用信息时,往往采用碎片化的 JSON 或自定义文档。这会导致软件分发时详情页展示不一、多语言支持混乱,甚至连基本的截图和版本日志都难以对齐。 为了解决这个问题,我们需要引入一套具备全球化视野的元数据定义标准。appstream 作为 Linux 生态下最重要的应用信息描述规范,能够通过结构化的 XML 标签,精准定义软件的身世、功能和展示资产。适配到鸿蒙平台后,它不仅能让你的重型“鸿蒙私有应用商店”瞬间具备吞金般的解析能力,

By Ne0inhk