【问题标题】:PyInstaller fatal error: Failed to execute scriptPyInstaller 致命错误:无法执行脚本
【发布时间】:2021-03-21 19:06:05
【问题描述】:

首先,我想为这个很长的问题道歉,但这让我发疯了。星期六我必须在学校的开放日展示这个项目,我几乎没有时间。

我和一个朋友(使用 Pygame)用 Python 3.9 编写了一个蛇游戏,我正在尝试使用 PyInstaller 从它创建一个可执行文件(使用多个 python 模块和附加文件,例如图像和音乐),但是每次我执行命令pyinstaller Game.spec 并尝试运行可执行文件时都会收到此错误:

这个错误对我来说非常出乎意料和奇怪,因为我已经在大约一周前以相同的方式使其可执行(但它是一个旧版本,我们更改了很多东西)并且它运行完美,但现在它不会了无论如何都无法正常工作,我们尝试了所有方法并阅读了 Stack 上的所有帖子,因此创建了可执行文件但它不会启动。

GIF 转换模块

自从我们制作了第一个可执行文件以来,我们确实改变了很多东西,但是代码的结构几乎保持不变,唯一的例外是我编写的一个模块,基本上它会自动将动画 GIF 分割成单独的帧并加载它们进入 Pygame(手动加载每一帧太浪费时间......)。我怀疑这个模块可能是最终导致我每次尝试执行游戏时都会提示该错误的原因之一。我们使用此模块为主菜单中的按钮设置动画:

它是如何工作的?

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]  

很抱歉代码乱七八糟,但我必须在大约 3 天内学习 OOP 才能编写所有这些,但我仍然有点困惑。无论如何,类的属性是不言自明的,gif 包含用户给出的所需动画图像,frames 数组将包含从动画 gif 中提取的所有图像,而assetFrames_urlframes 包含相对路径,我们用它绕过了 PyInstaller 中的另一个错误,该错误不允许我们将文件添加到 Game.spec,因此我们必须通过此函数传递所有附加文件,这里是 source这个函数。

我们不得不手写(我试图用一个脚本来自动化它,但它是一个巨大的失败)Game.spec 中每个附加元素的路径。使用deconstructGif方法,gif在特定文件夹中被分割(每个帧一个图像),然后使用gifLoader方法将所有分割帧加载到frames数组中,最后使用@方法进行动画处理987654342@.

例如,这些是动画按钮的文件夹:

游戏规范

当我们编译第一个可执行文件时,我们必须手动将每个文件的路径插入到元组数组中。这是最后一个版本:

        # -*- 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')

datas 数组中,我为每个文件插入了一个元组,第一个参数是图像的相对路径,第二个参数是文件夹的相对路径。本地路径由点 ('.') 表示。

我尝试过的事情:

  • 首先,我试图定位问题的“源头”,所以我打开了执行pyinstaller -i Icon.Ico --onefile Game.py命令生成的.spec文件(其中Ico.ico是可执行文件和游戏的图标) .py 主模块),我激活了控制台调试,如下所示:

               console=True, icon='Icon.ico')
    

这是我得到的详细错误:

  • 我尝试在数据数组中传递所有帧的路径,但没有成功。
  • 我尝试传入所有 GIF 的路径,但没有成功。

如果这个问题看起来令人困惑,并且语法确实很糟糕,但英语不是我的主要语言,我需要尽快解决这个问题,我没有时间纠正所有错误,我深表歉意。提前致谢!

【问题讨论】:

  • 看看我的answer是否有帮助,你需要一个帮助函数来确定安装程序中包含的文件的路径。

标签: python python-3.x pygame python-imaging-library pyinstaller


【解决方案1】:

最后,我设法解决了这个问题。

基本上,Pygame 和 PIL(Python 图像库)之间存在兼容性问题,我不得不重写整个 pyGimager 类,我无法生成单个可执行文件,但最终它可以工作。

【讨论】:

    猜你喜欢
    • 2018-08-17
    • 2023-03-15
    • 2017-11-22
    • 2016-09-10
    • 2021-05-30
    • 2021-02-14
    • 2020-08-31
    • 1970-01-01
    • 2019-08-03
    相关资源
    最近更新 更多