如何使用PyInstaller来创建Python可执行文件


如何使用PyInstaller来创建Python可执行文件

Python,尽管它功能强大,用途广泛,但却缺乏一些开箱即用的关键能力。首先,Python 没有提供将 Python 程序编译成独立可执行包的本地机制。

公平地说,Python 的原始使用情况从未要求独立包。总的来说,Python 程序是在有 Python 解释器副本的系统上原地运行的。但是,Python的急剧流行为在没有安装Python运行时的系统上运行Python应用程序创造了更大的需求。

[ Also on InfoWorld: 8 signs you're doing Python right ]

一些第三方已经为部署独立的Python应用程序设计了解决方案。其中最受欢迎的解决方案,也是最成熟的,是PyInstaller。PyInstaller并没有使打包Python应用程序的过程变得完全无痛,但它在这方面有很大的进步。

在这篇文章中,我们将探讨使用PyInstaller的基础知识,包括PyInstaller如何工作,如何使用PyInstaller来创建一个独立的Python可执行文件,如何微调你创建的Python可执行文件,以及如何避免使用PyInstaller时的一些常见陷阱。PyInstaller 可以安装在你的默认 Python 安装中,但最好为你要打包的项目创建一个虚拟环境,并在那里安装 PyInstaller。

PyInstaller 的工作方式是读取你的 Python 程序,分析它所做的所有导入,并将这些导入的副本与你的程序捆绑。PyInstaller 从你的程序的入口点读入。例如,如果你的程序的入口点是 myapp.py,你将运行 pyinstaller myapp.py 来进行分析。PyInstaller 可以检测并自动打包许多常见的 Python 包,比如 NumPy,但在某些情况下你可能需要提供提示。(

在分析了你的代码并发现它所使用的所有库和模块之后,PyInstaller 会生成一个 "规格文件"。这是一个扩展名为.spec的Python脚本,该文件包括关于你的Python应用程序需要如何打包的细节。当你第一次在你的应用程序上运行 PyInstaller 时,PyInstaller 将从头开始生成一个 spec 文件,并用一些合理的默认值来填充它。不要丢弃这个文件;它是完善PyInstaller部署的关键!

最后,PyInstaller将尝试从应用程序中生成一个可执行文件,并将其与所有的依赖项捆绑在一起。当它完成后,一个名为dist的子文件夹(默认情况下;你可以自由指定一个不同的名字)将出现在项目目录中。这又包含了一个目录,即您的捆绑应用程序--它有一个可运行的 .exe 文件,以及所有的库和其他所需的补充文件。

那么,您需要做的就是将这个目录打包成 .zip 文件或其他捆绑文件,以便分发您的程序。该捆绑文件通常需要在用户有写入权限的目录中解压,以便运行。

IDG

一个 .spec 文件被用来用 PyInstaller 创建一个可执行文件。注意在排除项中列出的命名空间。

测试PyInstaller包

你第一次尝试使用PyInstaller来打包一个应用程序时,很有可能不会完全成功。

要检查你的PyInstaller包是否工作,请导航到包含捆绑的可执行文件的目录,从命令行运行那里的.exe文件。

PyInstaller软件包失败的最常见原因是PyInstaller未能捆绑一个必要的文件。这种缺失的文件可分为几类:

隐藏或缺失的导入文件。有时PyInstaller无法检测到一个包或库的导入,通常是因为它是动态导入的。该软件包或库将需要手动指定。缺少独立文件。如果程序依赖于需要与程序捆绑的外部数据文件,PyInstaller没有办法知道。你将需要手动包含这些文件。缺少二进制文件。同样,如果你的程序依赖于一个外部二进制文件,如PyInstaller无法检测到的.DLL,你将需要手动包含它。

好消息是,PyInstaller提供了一个简单的方法来处理上述问题。由PyInstaller创建的.spec文件包括我们可以填写的字段,以提供PyInstaller遗漏的细节。

在文本编辑器中打开.spec文件并寻找Analysis对象的定义。传递给Analysis的几个参数是空白列表,但可以对它们进行编辑,以指定缺失的细节:

hiddenimports代表隐藏或缺失的进口。在这个列表中添加一个或多个字符串,其中包含你希望包含在你的应用程序中的库的名称。例如,如果你想添加 pandas 和 bokeh,你可以指定为 ['pandas', 'bokeh'] 。注意,有关的库必须安装在你运行 PyInstaller.datas 的同一个 Python 实例中,以防止丢失独立的文件。在这里添加一个或多个你想包含在你的项目树中的文件的规格。每个文件都必须以一个元组的形式传递,指明文件在你的项目目录中的相对路径和你想放置该文件的分发目录中的相对路径。例如,如果你有一个文件 ./models/mainmodel.dat 你想包含在你的应用程序中,并且你想把它放在你的分发目录中的一个匹配的子目录中,你将使用('./models/mainmodel.dat', './models' )作为 hiddenimports 列表中的一个条目。注意,你可以使用glob风格的通配符来指定一个以上的文件,binaries用于丢失的独立二进制文件。和数据一样,你可以使用 binaries 来传递一个图元列表,指定项目树中二进制文件的位置和它们在分发目录中的目的地。

请记住,传递给Analysis的任何列表都可以在.spec文件的前面以编程方式生成。毕竟,.spec 文件只是一个 Python 脚本的另一个名字。

在你对 .spec 文件进行修改后,重新运行 PyInstaller 来重建软件包。然而,从现在开始,一定要把修改后的 .spec 文件作为参数传递给它 (例如 pyinstaller myapp.spec)。像以前一样测试可执行文件。

最后,当你确信一切都按计划进行时,你可能想编辑 .spec 文件以防止你打包的应用程序在启动时出现一个命令行窗口。在.spec文件的EXE对象设置中,设置控制台=False。如果你的应用程序有一个GUI,而你不希望一个虚假的命令行窗口将用户引入歧途,那么抑制控制台是很有用的。当然,如果你的应用程序需要一个命令行,请不要改变这个设置。

完善PyInstaller包

一旦你用PyInstaller打包了你的应用程序并正常运行,你可能想做的下一件事就是把它精简一下。

由于Python是一种动态语言,很难预测一个特定的程序在运行时需要什么。出于这个原因,当 PyInstaller 检测到一个包的导入时,它将包括该包中的所有内容,无论它是否在运行时被你的程序使用。

这里有一个好消息。PyInstaller 包含了一种机制,可以选择性地排除整个包或包中的单个命名空间。例如,假设你的程序导入了包foo,其中包括foo.bar和foo.bip。如果你知道你的程序只使用foo.bar中的逻辑,你可以安全地排除foo.bip并节省一些空间。

要做到这一点,你可以使用传递给.spec文件中的分析对象的排除参数。你可以传递一个名字的列表--顶级模块,或者带点的命名空间--来从你的包中排除。例如,要排除foo.bip,你可以简单地指定['foo.bip']。

IDG

由PyInstaller创建的可交付目录。由于该目录中有大量的文件,像 NSIS 这样的第三方安装项目可以用来将该目录打包成一个自解压档案,并自动创建一个可执行文件的快捷方式。

你可以做的一个常见的排除是 tkinter,用于创建简单跨平台图形用户界面的 Python 库。默认情况下,tkinter 和它所有的支持文件都被打包在 PyInstaller 项目中。如果你在你的项目中不使用 tkinter,你可以通过在排除列表中添加'tkinter'来排除它。省略 tkinter 将使包的大小减少约 7 MB。

另一个常见的排除项是测试套件。如果你的程序导入的包有一个测试套件,那么这个测试套件最终可能会被包含在你的PyInstaller包中。除非你在你部署的程序中实际运行测试套件,否则你可以安全地排除它。

请记住,使用排除法创建的包应该在使用前彻底测试。如果你最终排除了一些你没有预料到的未来场景中使用的功能,你的应用程序将会崩溃。

PyInstaller提示在你计划部署的操作系统上构建你的PyInstaller包。PyInstaller不支持跨平台的构建。如果你需要在MacOS、Linux和Windows系统上部署你的独立Python应用程序,那么你将需要安装PyInstaller并在每个操作系统上构建单独的应用程序版本。在开发你的应用程序时构建你的PyInstaller包。一旦你知道你将用PyInstaller部署你的项目,就立即构建你的.NET包。spec文件,并在开发你的应用程序的同时开始完善PyInstaller包。这样,你就可以在开发过程中添加排除项或包含项,并在你编写应用程序时测试新功能的部署方式。PyInstaller包括一个命令行开关--onefile,它将你的整个应用打包成一个自解压的可执行文件。这听起来是个好主意--你只需要提供一个文件!但它有一些缺陷。- 但它也有一些隐患。每当你运行该应用程序时,它必须首先将可执行文件中的所有文件解压到一个临时目录。如果应用程序很大(例如,200MB),解包可能意味着几秒钟的延迟。请使用默认的单目录模式,并将所有文件打包成一个.zip文件。如果你想用某种方式来部署你的应用程序,而不是一个.zip文件,可以考虑使用一个安装程序工具,如开源的Nullsoft可脚本安装系统。它对可交付文件的大小只增加了很少的开销,并且可以让你配置安装过程的许多方面,比如为你的可执行文件创建快捷方式。PyInstaller是一个打包系统,不是一个编译器或优化器。用 PyInstaller 打包的代码不会比在原始系统上运行时更快。如果你想加速Python代码,请使用适合该任务的C语言加速库,或者像Cython这样的项目。如何用Python做更多的事情Cython教程。如何加速Python如何以聪明的方式安装Python用Poetry更好地管理Python项目Virtualenv和venv。Python虚拟环境解释Python virtualenv和venv的注意事项Python线程和子进程解释如何使用Python调试器如何使用timeit对Python代码进行剖析如何使用cProfile对Python代码进行剖析在Python中开始使用async如何在Python中使用asyncio如何将Python转换为JavaScript(然后再返回)。


本文标签

热门标签

会员评论