[英]PyInstaller fatal error: Failed to execute script
First of all, I want to apologize for the very long question but this is driving me crazy.首先,我想为这个很长的问题道歉,但这让我发疯了。 Saturday I have to exhibit this project to my school's open day and I have little to no time.
星期六我必须在学校的开放日展示这个项目,我几乎没有时间。
I've written a snake game in Python 3.9 with a friend (using Pygame) and I'm trying to create an executable file with PyInstaller from it (using multiple python modules and additional files such as images and music), but every time I execute the command pyinstaller Game.spec
and I try to run the executable I get this error:我和一个朋友(使用 Pygame)在 Python 3.9 中编写了一个蛇游戏(使用 Pygame),我正在尝试使用 PyInstaller 从它创建一个可执行文件(使用多个 python 模块和附加文件,如图像和音乐),但每次我执行命令
pyinstaller Game.spec
并尝试运行可执行文件我收到此错误:
This error is very unexpected and strange to me because I already made it executable about a week ago (but it was an older version and we change lots of things) in the same way and it worked flawlessly, but now it won't work in any way, we tried everything and read every post here on Stack, so the executable gets created but it won't start.这个错误对我来说非常出乎意料和奇怪,因为我已经在大约一周前以相同的方式使其可执行(但它是一个较旧的版本,我们更改了很多东西)并且它完美地工作,但现在它无法工作无论如何,我们尝试了所有方法并阅读了 Stack 上的每一篇文章,因此创建了可执行文件,但它不会启动。
We changed really a lot of things since we made the first executable, but the structure of the code remained pretty much the same with the only exception of a module that I wrote, basically it automatically splits animated GIFs into separated frames and loads them into Pygame (loading every single frame by hand was too time-wasting...).自从我们制作了第一个可执行文件以来,我们确实改变了很多东西,但代码的结构几乎保持不变,唯一的例外是我编写的一个模块,基本上它会自动将动画 GIF 分割成单独的帧并将它们加载到 Pygame (手动加载每一帧太浪费时间了......)。 I suspect that this module might be one of the causes that ultimately lead to prompting that error every time I try to execute the game.
我怀疑这个模块可能是最终导致我每次尝试执行游戏时都会提示该错误的原因之一。 We used this module to animate the buttons in the main menu:
我们使用此模块为主菜单中的按钮设置动画:
from PIL import Image
import sys
import os
import pygame
class PyGimager:
def __init__(self, gif):
# Loading the desired gif image
self.gif = Image.open(gif)
# Variable where all the frames will be stored
self.frames = []
self.assetFrames_url = []
# This method divides all the frames of the gif in a .png file (in a desired folder)
def deconstructGif(self, mainName='decImage', savePath='LOCAL'):
path = savePath + "/" + mainName
self.assetFrames_url.append(resource_path(path))
local = True
if savePath != 'LOCAL':
try:
os.makedirs(savePath)
except OSError as error:
print("Path creation failed: {}".format(error))
local = False
for i in range(self.gif.n_frames):
self.gif.seek(i)
if not local:
self.gif.save(savePath + mainName + '{}.png'.format(i), 'PNG')
else:
self.gif.save(mainName + '{}.png'.format(i))
# loads all the frames in a bidimensional array
def gifLoader(self, loadPath="/"):
frame = ''
if loadPath == "/":
for image in os.listdir():
if image.endswith(".png"):
frame = pygame.image.load(image)
self.frames.append(frame)
else:
for image in os.listdir(loadPath):
if image.endswith(".png"):
frame = pygame.image.load(loadPath + image)
self.frames.append(frame)
def gifPlayer(self, screen, position=def_position, wait=500):
for frame in self.frames:
AnimatedSprite = frame
screen.blit(AnimatedSprite, position)
pygame.time.wait(wait)
pygame.display.update()
def getFirstFrame(self):
return self.frames[0]
Sorry for the messy code but I had to learn OOP in about 3 days to write all of this and I am still a bit confused.抱歉代码乱七八糟,但我必须在大约 3 天的时间里学习 OOP 才能写出所有这些,我仍然有点困惑。 Anyway, the attributes of the class are pretty much self-explanatory,
gif
contains the desired animated image given by the user, the frames
array will contain all the images extracted from the animated gif while assetFrames_url
is a copy of frames
containing the relative paths, we used it to bypass another bug in PyInstaller which didn't allow us to add our files to Game.spec
, so we had to pass through this function all the additional files, here's the source of this function.无论如何,class 的属性几乎是不言自明的,
gif
包含用户提供的所需动画图像, frames
数组将包含从动画 gif 中提取的所有图像,而assetFrames_url
是包含相对路径的frames
的副本,我们用它绕过了 PyInstaller 中的另一个错误,该错误不允许我们将文件添加到Game.spec
,所以我们必须通过这个 function 的所有附加文件,这里是这个 function 的来源。
We had to write by hand (I tried to automate it with a script but it was a huge failure) the path of every single additional element inside Game.spec
.我们不得不手动编写
Game.spec
中每一个附加元素的路径(我试图用一个脚本来自动化它,但这是一个巨大的失败)。 With the method deconstructGif
the gif gets split (one image for each frame) in a specific folder, then all the split frames are loaded inside the frames
array with the gifLoader
method and finally they get animated with the method gifPlayer
.使用
deconstructGif
方法,gif 在特定文件夹中被分割(每帧一个图像),然后使用 gifLoader 方法将所有分割帧加载到frames
组中,最后使用gifLoader
方法对它们进行动画gifPlayer
。
For example, these are the folders of the animated buttons:例如,这些是动画按钮的文件夹:
When we compiled the first executable we had to manually insert the path for each file inside an array of tuples.当我们编译第一个可执行文件时,我们必须手动将每个文件的路径插入到元组数组中。 This is the last version:
这是最后一个版本:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['Game.py'],
pathex=['C:\\Users\\gianm\\Documents\\GitKraken\\pyWormy'],
binaries=[],
datas=[
('Img/Buttons/Hard/HardButton0.png','Img/Buttons/Hard/'),('Img/Buttons/Hard/HardButton1.png','Img/Buttons/Hard/'),
('Img/Buttons/Easy/EasyButton0.png','Img/Buttons/Easy/'),('Img/Buttons/Easy/EasyButton1.png','Img/Buttons/Easy/'),
('Img/Buttons/Options/OptionsButton0.png','Img/Buttons/Options/'),('Img/Buttons/Options/OptionsButton1.png','Img/Buttons/Options/'),
('Img/Buttons/Play/PlayButton0.png','Img/Buttons/Play/'),('Img/Buttons/Play/PlayButton1.png','Img/Buttons/Play/'),
('Img/Buttons/Exit/ExitButton0.png','Img/Buttons/Exit/'),('Img/Buttons/Exit/ExitButton1.png','Img/Buttons/Exit/'),
('Img/Buttons/BackToMenu/BacktoMenuButton0.png','Img/Buttons/BackToMenu/'),('Img/Buttons/BackToMenu/BacktoMenuButton1.png','Img/Buttons/BackToMenu/'),
('SF_Pixelate.ttf','.'),
('Sounds/difficileSottofondo.wav','Sounds/'),('Sounds/facileSottofondo.wav','Sounds/'),('Sounds/lose.wav','Sounds/'),('Sounds/slurp.wav','Sounds/'),('Sounds/musica.wav','Sounds/'),
('Img/background.png','Img/'),('Img/GameOver.png','Img/'),('Img/startMenu.png','Img/'),
('Img/Sprites/Sprites3/CorpoSerpente.png','Img/Sprites/Sprites3/'),
('Img/Sprites/Sprites3/TestaDestra.png','Img/Sprites/Sprites3/'), ('Img/Sprites/Sprites3/TestaGiu.png','Img/Sprites/Sprites3/'),('Img/Sprites/Sprites3/TestaSinistra.png','Img/Sprites/Sprites3/'),('Img/Sprites/Sprites3/TestaSopra.png','Img/Sprites/Sprites3/'),
('Img/Sprites/Sprites3/Mela/C.png','Img/Sprites/Sprites3/Mela/'),('Img/Sprites/Sprites3/Mela/Ruby.png','Img/Sprites/Sprites3/Mela/'),('Img/Sprites/Sprites3/Mela/PHP.png','Img/Sprites/Sprites3/Mela/'),('Img/Sprites/Sprites3/Mela/JS.png','Img/Sprites/Sprites3/Mela/'),
('Img/Buttons/Hard.gif','Img/Buttons/'),('Img/Buttons/Easy.gif','Img/Buttons/'),('Img/Buttons/Options.gif','Img/Buttons/'),('Img/Buttons/Exit.gif','Img/Buttons/'),
('Img/Buttons/BackToMenu.gif','Img/Buttons/'),('Img/Buttons/Play.gif','Img/Buttons/'),
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='pyWormy',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False , icon='Icon.ico')
Inside the datas
array, I inserted a tuple for each file, the first argument is the relative path of the image while the second is the relative path of the folder.在
datas
数组中,我为每个文件插入了一个元组,第一个参数是图像的相对路径,第二个参数是文件夹的相对路径。 The local paths are represented by a point ('.').本地路径由点 ('.') 表示。
First of all, I tried to locate the "source" of the problem, so I opened the .spec
file generated with the execution of the command pyinstaller -i Icon.Ico --onefile Game.py
(with Ico.ico being the icon of the executable and Game.py the main module) and I activated the console debug, like this:首先,我试图找到问题的“根源”,所以我打开了执行命令
pyinstaller -i Icon.Ico --onefile Game.py
生成的.spec
文件(其中 Ico.ico 是图标可执行文件和 Game.py 主模块),我激活了控制台调试,如下所示:
console=True, icon='Icon.ico')
This is the error that i get in detail:这是我详细得到的错误:
I apologize if this question may seem confusing and if the grammar is really bad but English is not my primary language and I need to fix this fast and I don't have time to correct all the mistakes.如果这个问题可能看起来令人困惑,并且语法真的很糟糕,但英语不是我的主要语言,我需要快速解决这个问题,我没有时间纠正所有错误,我深表歉意。 Thanks in advance!
提前致谢!
Finally, I managed to solve this.最后,我设法解决了这个问题。
Basically, there is a compatibility issue between Pygame and PIL (Python Imaging Library), I had to rewrite the entire pyGimager class and I was not able to make a single executable file but in the end, it works.基本上,Pygame 和 PIL(Python 图像库)之间存在兼容性问题,我不得不重写整个 pyGimager class 并且我无法制作单个可执行文件,但最终它可以工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.