Неустранимая ошибка PyInstaller: не удалось выполнить скрипт

Прежде всего, я хочу извиниться за очень длинный вопрос, но это сводит меня с ума. В субботу я должен выставить этот проект на день открытых дверей в моей школе, и у меня практически нет времени.

Я написал змеиную игру на Python 3.9 с другом (используя Pygame) и пытаюсь создать из нее исполняемый файл с помощью PyInstaller (используя несколько модулей Python и дополнительные файлы, такие как изображения и музыка), но каждый раз я выполнить команду pyinstaller Game.spec и я пытаюсь запустить исполняемый файл, я получаю эту ошибку:

Эта ошибка очень неожиданна и странна для меня, потому что я уже сделал ее исполняемой около недели назад (но это была более старая версия, и мы многое меняем) таким же образом, и она работала без нареканий, но теперь она не будет работать в в любом случае, мы перепробовали все и прочитали все сообщения здесь, в стеке, поэтому исполняемый файл создается, но не запускается.

Модуль конвертера 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 дня, чтобы написать все это, и я все еще немного запутался. В любом случае, атрибуты класса говорят сами за себя: gif содержит желаемое анимированное изображение, заданное пользователем, массив frames будет содержать все изображения, извлеченные из анимированного gif, а assetFrames_url является копией frames, содержащей относительные пути, мы использовали его, чтобы обойти еще одну ошибку в PyInstaller, которая не позволяла нам добавлять наши файлы в Game.spec, поэтому нам пришлось пропустить через эту функцию все дополнительные файлы, вот источник этой функции.

Нам пришлось прописывать вручную (я пытался автоматизировать это с помощью скрипта, но это был огромный провал) путь каждого дополнительного элемента внутри Game.spec. С помощью метода deconstructGif гифка разделяется (одно изображение на каждый кадр) в определенной папке, затем все разделенные кадры загружаются в массив frames методом gifLoader и, наконец, анимируются методом gifPlayer.

Например, это папки анимированных кнопок:

Game.spec

Когда мы скомпилировали первый исполняемый файл, нам пришлось вручную вставить путь для каждого файла в массив кортежей. Это последняя версия:

        # -*- 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 я вставил кортеж для каждого файла, первый аргумент — это относительный путь к изображению, а второй — относительный путь к папке. Локальные пути представлены точкой ('.').

Что я пробовал:

  • Прежде всего, я попытался найти «источник» проблемы, поэтому я открыл файл .spec, сгенерированный при выполнении команды pyinstaller -i Icon.Ico --onefile Game.py (где Ico.ico — это значок исполняемого файла, а Game.py — основной модуль) и Я активировал отладку консоли, например:

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

Это ошибка, которую я получаю подробно:

  • Пробовал передать в массиве данных пути для всех кадров, не получилось.
  • Пробовал пройти по путям всех гифок, не получилось.

Я извиняюсь, если этот вопрос может показаться запутанным, и если грамматика действительно плохая, но английский не является моим основным языком, и мне нужно исправить это быстро, и у меня нет времени, чтобы исправить все ошибки. Заранее спасибо!

Посмотрите, поможет ли мой ответ, вам нужна вспомогательная функция, чтобы определить путь к файлам, включенным в ваш установщик.

import random 10.12.2020 12:17
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
661
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Наконец, мне удалось решить эту проблему.

По сути, существует проблема совместимости между Pygame и PIL (Python Imaging Library), мне пришлось переписать весь класс pyGimager, и я не смог создать ни одного исполняемого файла, но, в конце концов, он работает.

Другие вопросы по теме