Pyinstaller 4.4官方手册 3# Pyinstaller是什么?是如何工作的?

原文链接:https://pyinstaller.readthedocs.io/en/v4.4/operating-mode.html

本节介绍 PyInstaller 的基本概念,这些概念适用于所有平台。 在“使用Pystaller”章节下,会介绍选项与特殊情况。

PyInstaller 会读取您编写的 Python 脚本,它会分析您的代码以发现您的脚本需要的所有其他模块和库。 然后它收集所有这些文件的副本(包括活动的 Python 解释器)并将它们与您的脚本放在一个文件夹中,还可以选择放在一个可执行文件中。

对于绝大多数程序,这可以通过一个简短的命令来完成:

pyinstaller myscript.py

或添加一些选项,例如以一个带窗口应用程序的单个可执行文件:

pyinstaller --onefile --windowed myscript.py

你可以将打好的包作为文件夹或文件发给其他人,让他们可以执行你的程序。对于用户来说,该应用程序是独立的,用户不需要安装任何特定版本的 Python 或任何模块。

注意:
Pyinstaller针对现行的操作系统与现行的Python,产生特定的输出。
这意味着需要针对不同的操作系统、不同版本的 Python、32 位或 64 位操作系统,分别进行输出。
执行 PyInstaller 的 Python 解释器是包的一部分,不同的操作系统和字长有特定的解释器。

分析:查找程序需要的文件

你的脚本还需要哪些其他模块和库才能运行? (这些有时被称为“依赖关系”。)
为了找出所需要的依赖关系,PyInstaller 会查找脚本中的所有导入语句(import 语句)。 它会从查找到导入语句种找到导入的模块,以此类推,直到查找完脚本里可能使用的模块的完整列表。
PyInstaller 知道 Python 包常用的“egg”分发格式,如果您的脚本从“egg”导入一个模块,PyInstaller 会将 egg 及其依赖项添加到所需文件集中。
PyInstaller 还知道许多主要的 Python 包,包括 GUI 包 Qt(通过 PyQt 或 PySide 导入)、WxPython、TkInter、Django 和其他主要包。 有关完整列表,请参阅支持的软件包

某些 Python 脚本以 PyInstaller 无法检测到的方式导入模块:例如,通过使用 import() 函数和变量数据、使用 importlib.import_module() 或在运行时操作 sys.path 值。
如果你的脚本需要导入 PyInstaller 无法自动检测到的文件,做如下操作:

  • 在 pyinstaller 命令行上提供附加文件。
  • 在命令行上提供额外的导入路径。
  • 编辑第一次为脚本运行PyInstaller时编写的 myscript.spec 文件。在规范文件(spec file)中,你可以告诉 PyInstaller 你的脚本特殊的代码模块。
  • 可以编写“钩子”文件以告知 PyInstaller 导入的隐藏内容。如果你为其他用户可能使用的包创建了一个“钩子”,你可以将你的钩子文件贡献给 PyInstaller。

如果程序依赖于对某些数据文件的访问,你可以通过修改规范文件来使 PyInstaller 将这些文件包含在包中。 这是“使用规范文件”(Using Spec Files)中介绍的高级用法。
为了在Pyinstaller运行时定位脚本所包含的文件,不管这些路径是否有包中需要的文件,您的程序需要能够在运行时了解其路径,该部分会在“运行信息”章节中介绍。

PyInstaller 不包含任何在操作系统中都应该存在的库。 例如在 GNU/Linux 中,它不会打包来自 /lib 或 /usr/lib 路径的文件,如果这些文件是每个系统中都能找到的。

打包到单一文件夹

当你将 PyInstaller 应用到 myscript.py 时,默认生成一个名为 myscript 的文件夹
该文件夹包含脚本所有的依赖项,以及一个名为 myscript(Windows 中为 myscript.exe)的可执行文件。将该文件夹压缩为 myscript.zip 并将其分发给你的用户,用户们只需解压缩即可实现程序的安装,他们可以打开文件夹并启动其中的 myscript 可执行文件来运行你的应用程序。

使用单文件夹模式,便于在构建应用程序过程中出现问题时进行调试。 你可以确切地看到 PyInstaller 汇总到文件夹中的文件。
单一文件夹打包模式的另一个优点是:当你更改代码时,只要它导入和之前的文件完全相同的一组依赖项,你就可以只发送更新的 myscript 可执行文件(通常比整个文件夹小); 如果你更改了脚本,同时升级或导入更多、不同的依赖项,当再次进行分发时,必须重新发整个包。
单一文件夹打包模式的缺点是:包含大量文件。 用户必须在一长串名称或一大堆图标中找到 myscript 可执行文件。 此外,用户可能会因不小心将文件拖出文件夹而造成一些问题。

单一文件夹程序的工作原理

打包程序始终在 PyInstaller 引导的加载程序中开始, 这是文件夹中的 myscript 可执行文件的核心。PyInstaller bootloader(引导加载程序)是在平台上(Windows、GNU/Linux、Mac OS X 等)运行的二进制可执行程序。当用户启动你的程序,运行的是引导加载程序。 引导加载程序会创建一个临时 Python 环境,以便 Python 解释器在 myscript 文件夹中找到所有导入的模块和库。(以上为概述。更多详细信息,请参阅下面的 Bootstrap 过程详解。)

打包到单个文件

PyInstaller 可以将你的脚本及其所有依赖项打包到一个名为 myscript(Windows 中的 myscript.exe)的可执行文件中。
优点是:用户只要运行单个可执行文件就可以获得他们想要的东西。
缺点是:任何相关文件(例如 README)都必须单独分发。 此外,单个可执行文件的启动速度比单一文件夹打包要慢一些。
在尝试打包成单个文件之前,请确保你的应用程序在打包到单一个文件夹时正常工作,在单一文件夹模式下诊断问题要容易得多。

单个文件程序的工作原理

Bootloader(引导加载程序)也是单文件包的核心。
启动时,它会在此操作系统的临时文件夹中创建一个临时文件夹。 该文件夹名为_MEIxxxxxx,其中xxxxxx 是一个随机数。
一个可执行文件,包含脚本使用的所有 Python 模块的嵌入式存档,以及任何非 Python 支持文件(例如 .so 文件)的压缩副本。引导加载程序解压缩支持文件并将副本写入临时文件夹,这可能需要一点时间。 这就是为什么单文件应用程序比单文件夹应用程序启动要慢一点的原因。

注意:PyInstaller 当前不保留文件属性。

创建完临时文件夹后,引导加载程序在临时文件夹的上下文中与单一文件夹打包的流程完全相同。 当打包代码结束时,引导加载程序会删除临时文件夹。(在 GNU/Linux 和相关系统中,可以使用“no-execution”选项挂载 /tmp 文件夹。该选项与 PyInstaller 单文件打包不兼容。它需要从 /tmp 执行代码。 如果您知道目标环境,可运行 --runtime-tmpdir 可能有效。)

如果程序崩溃或被终止(Unix 上的 kill -9,Windows 上的任务管理器终止,Mac OS 上的“强制退出”),_MEIxxxxxx 文件夹不会被删除。 因此,如果您的应用程序频繁崩溃,将产生多个 _MEIxxxxxx 临时文件夹,进而使用户浪费更多的磁盘空间。

可以使用 --runtime-tmpdir 命令行选项控制 _MEIxxxxxx 文件夹的位置。在可执行文件中指定存储路径,引导加载程序将在指定文件夹内创建_MEIxxxxxx 文件夹。 有关详细信息,请参阅定义提取位置

注意:

  • 不要为单文件可执行程序授予管理员权限(Unix/Linux 中的 setuid root 或 Windows 7 中的“以管理员身份运行此程序”属性)。 因为存在这样一种可能:恶意攻击者可能会在引导加载程序准备临时文件夹时破坏其中一个共享库。可以改为以单文件夹模式分发特权程序。
  • 使用 os.setuid() 的应用程序可能会遇到权限错误。 调用 setuid 后,打包程序运行的临时文件夹可能无法读取。 如果您的脚本需要调用 setuid,最好使用单文件夹模式,以便更好地控制其文件的权限。

使用控制台窗口

默认情况下,引导加载程序会创建一个命令行控制台(GNU/Linux 和 Mac OS 中的终端窗口,Windows 中的命令行窗口)。 它将这个窗口提供给 Python 解释器用于标准输入、输出,脚本所使用的 print 和 input() 的功能也会出现在这里。 来自 Python 的错误消息和默认日志输出也会出现在控制台窗口。

Windows 和 Mac OS 的可以选择让 PyInstaller 不提供控制台窗口。 引导加载程序在没有标准输出、输入目标的情况下启动 Python。 当您的脚本具有用于用户输入的图形界面并且可以正确报告其自己的诊断时,请执行上述操作。

如 CPython 教程附录中所述,对于 Windows,运行.pyw 的文件扩展名的文件时,会出现控制台窗口。 同样,在 PyInstaller 中使用 myscript.pyw 脚本时,也不会提供控制台窗口。

隐藏源代码

打包完成的应用程序不包含任何源代码。 但是,PyInstaller 打包了已编译的 Python 脚本(.pyc 文件)。 这些文件原则上可以被反编译以展示你的代码逻辑。

如果你想更彻底地隐藏你的源代码,可以用 Cython 编译你的一些模块。 使用 Cython,你可以将 Python 模块转换为 C 并将 C 编译为机器语言。 PyInstaller 可以遵循引用 Cython C 对象模块的 import 语句,并将它们捆绑在一起。

此外,通过在 PyInstaller 的命令行上指定加密密钥,可以使用 AES256 混淆 Python 字节码。 请注意,提取密钥并取回原始字节码仍然很容易,但它应该可以防止大多数形式的“随意”篡改。 有关详细信息,请参阅 Python 字节码加密

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值