使用PyInstaller捆绑游戏#
您已经使用Arcade编写了您的游戏,它是一部杰作!恭喜你!现在你想和其他人分享它。这通常意味着帮助人们安装Python,下载必要的模块,复制您的代码,然后让它们都正常工作。分享并不是一件容易的事情。井, PyInstaller 可以改变这一切!
PyInstaller 是一种用于Python的工具,它允许您将整个Python应用程序捆绑成一个可以轻松共享的单文件可执行捆绑包。谢天谢地,它在Arcade上工作得很好!
我们将演示Windows的用法,但在Windows、Mac和Linux上,一切都应该完全相同。请注意,您只能为您所在的系统构建。这意味着,为了构建Windows版本,您必须在Windows机器上运行,对于Linux和Mac也是如此。
捆绑一个简单的Arcade脚本#
为了演示PyInstaller的工作原理,我们将:
安装PyInstaller
创建一个使用Arcade的简单示例应用程序
将应用程序捆绑到一个文件的可执行文件中
运行应用程序
首先,确保在您的Python环境中安装了Arcade和PyInstaller,并具有:
pip install arcade pyinstaller
那我们就需要我们的比赛。在这种情况下,我们将从简单开始。我们需要一个一个文件的游戏,不需要任何额外的图像或声音。一旦我们让它发挥作用,我们就可以变得更加复杂。创建名为的文件 main.py
其中包含以下内容:
import arcade
arcade.open_window(400, 400, "My Game")
self.clear()
arcade.draw_circle_filled(200, 200, 100, arcade.color.BLUE)
arcade.finish_render()
arcade.run()
现在,通过从命令行运行PyInstaller来创建一个文件可执行捆绑包文件:
pyinstaller main.py --onefile
PyInstaller生成作为游戏捆绑包的可执行文件。它把它放在 dist\
文件夹位于当前工作目录下。查找名为的文件 main.exe
在……里面 dist\
。运行此命令并查看示例应用程序启动!
您可以将此文件复制到计算机上的任何位置并运行它。或者,与其他人分享。您的脚本所需的一切都在这个可执行文件中。
对于简单的游戏,这就是你需要知道的全部!但是,如果您的游戏从磁盘加载任何类型的数据文件,请继续阅读。
处理数据文件#
在创建包时,PyInstaller首先检查您的项目,并自动识别项目所需的几乎所有内容(一个Python解释器、已安装的模块等)。但是,它不能自动确定您的游戏正在从磁盘加载哪些数据文件(图像、声音、地图)。因此,您必须显式地告诉PyInstaller有关这些文件以及它应该将它们放在包中的位置。这是使用PyInstaller的 --add-data
标志:
pyinstaller main.py --add-data "stripes.jpg;."
传递给 --add-data
是“源”文件或目录(例如: stripes.jpg
)标识PyInstaller应该在捆绑包中包含什么。分号后面的项是“Destination”(例如:“.
”),它指定相对于包的根应该将文件放在包中的什么位置。在上面的示例中, stripes.jpg
将图像复制到捆绑包的根目录(“.
”)。
在指示PyInstaller将数据文件包含在包中之后,必须确保代码从正确的目录加载数据文件。当您共享您的游戏包时,您无法控制用户将从哪个目录运行您的包。只有一个文件的PyInstaller包在运行时被解压缩到一个随机的临时目录,然后从那里执行,这让情况变得复杂起来。本文档描述了一种简单的方法,它允许您的代码在PyInstaller捆绑包中运行时执行和加载文件,并且在未捆绑时也能够运行。
你需要做两件事。首先,下面的代码片段必须放在脚本的开头:
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
os.chdir(sys._MEIPASS)
此代码段使用 sys.frozen
和 sys._MEIPASS
,这两个都是由PyInstaller设置的。这个 sys.frozen
设置指示代码是否从包运行(“冻结”)。如果代码被“冻结”,则工作目录将更改为包解压缩到的根目录 (sys._MEIPASS
)。PyInstaller通常将其一个文件捆绑包解压缩到一个名为类似以下内容的目录中: C:\Users\user\AppData\Local\Temp\_MEI123456
。
其次,一旦上面的代码设置了当前工作目录,代码中的所有文件路径都可以是相对路径(例如: resources\images\stripes.jpg
)而不是绝对路径(例如: C:\projects\mygame\resources\images\stripes.jpg
)。如果您完成这两件事并将数据文件添加到包中,如下所示,您的代码将能够“正常”运行以及在捆绑包中运行。
下面是一些示例,它们展示了如何将数据文件包含在一个PyInstaller包中的一些常见模式。这些示例首先显示了一个代码片段,该代码片段演示了如何加载数据(相对路径名),然后是将数据文件复制到包中的PyInstaller命令。他们都认为 os.chdir()
正在使用上面列出的代码片段。
一个数据文件#
如果您只是在与脚本相同的目录中有一个数据文件,请使用如下所示的相对路径引用该数据文件:
sprite = arcade.Sprite("stripes.jpg")
然后,使用如下所示的PyInstaller命令将数据文件包含在捆绑的可执行文件中:
pyinstaller main.py --add-data "stripes.jpg;."
...or...
pyinstaller main.py --add-data "*.jpg;."
一个数据目录#
如果您有一个数据文件目录(如 images
),则使用如下所示的相对路径引用数据目录:
sprite = arcade.Sprite("images/player.jpg")
sprite = arcade.Sprite("images/enemy.jpg")
然后,使用如下所示的PyInstaller命令将该目录包含在捆绑的可执行文件中:
pyinstaller main.py --add-data "images;images"
多个数据文件和目录#
您可以使用 --add-data
多次标记以将多个文件和目录添加到包中:
pyinstaller main.py --add-data "player.jpg;." --add-data "enemy.jpg;." --add-data "music;music"
一个目录,一应俱全#
尽管您可以使用单独的 --add-data
标志,建议您编写游戏,以便所有数据文件都位于一个根目录下,通常名为 resources
。您可以使用子目录来帮助组织所有内容。示例目录树如下所示::
project/
|--- main.py
|--- resources/
|--- images/
| |--- enemy.jpg
| |--- player.jpg
|--- sound/
| |--- game_over.wav
| |--- laser.wav
|--- text/
|--- names.txt
使用这种方法,可以很容易地将所有数据绑定到一个 --add-data
旗帜。您的代码将使用相对路径名来加载资源,如下所示:
sprite = arcade.Sprite("resources/images/player.jpg")
text = open("resources/text/names.txt").read()
并且,您可以将整个目录树包括到包中,如下所示:
pyinstaller main.py --add-data "resources;resources"
为了保持捆绑过程的简单性,有必要花点时间来计划如何布局和加载数据文件。
上述处理数据文件的技术只是一种方法。如果希望在处理数据文件时获得更好的控制和灵活性,请阅读 PyInstaller Run-Time Information 文档。
现在你知道如何安装PyInstaller,包括数据文件,并将你的游戏捆绑成一个可执行文件,你就有了捆绑游戏并与你的新粉丝分享它所需的东西!
故障排除#
使用单文件夹捆绑包进行故障排除#
如果您在使捆绑包正常工作时遇到问题,暂时省略 --onefile
旗帜来自 pyinstaller
指挥部。这将把你的游戏捆绑成一个文件夹捆绑包,里面有一个可执行文件。这使您可以检查文件夹的内容,并确保所有文件都位于您期望的位置。由生成的一个文件包 --onefile
只是这个单文件夹捆绑包的自解压缩存档。
PyInstaller未捆绑所需的模块#
在大多数情况下,PyInstaller能够分析您的项目并自动确定将哪些模块放入包中。但是,如果PyInstaller碰巧错过了一个模块,您可以使用 --hidden-import MODULENAME
用于显式指示PyInstaller包括模块的标志。请参阅 PyInstaller documentation 了解更多详细信息。
额外细节#
您会注意到,在运行
pyinstaller
,a.spec
文件将出现在您的目录中。该文件是由PyInstaller生成的,不需要保存或签入您的源代码资源库。由PyInstaller生成的可执行单文件捆绑包
--onefile
FLAG的启动速度将慢于原始应用程序或单文件夹捆绑包。这是意料之中的,因为一个文件包最终只是一个压缩文件夹,所以每次运行包时,它们必须花时间解压缩自己。默认情况下,当PyInstaller创建捆绑的应用程序时,该应用程序会打开一个控制台窗口。您可以通过添加
--windowed
标志添加到pyinstaller
指挥部。有关上述主题的更多详细信息,请参阅下面的PyInstaller文档。
本教程使用的是PyInstaller 4.x。
PyInstaller文档#
PyInstaller是一种灵活的工具,可以处理各种不同的情况。欲进一步阅读,请参考以下链接,链接至PyInstaller官方文档和GitHub页面:
PyInstaller手册:https://pyinstaller.readthedocs.io/en/stable/
PyInstaller GitHub:https://github.com/pyinstaller/pyinstaller