Pygame ne charge pas png après la fabrication.exe avec Pyinstaller

j'ai essayé de faire un .une ex de chez moi .c'est très frustrant.

J'utilise Python 3.5.2, Pygame 1.9.2 et Pyinstaller 3.2.

le jeu fonctionne parfaitement comme .py, mais après j'entre pyinstaller --debug game.py , le .exe est construit et je l'exécute, j'obtiens ce qui suit:

debug "et" écran 1519130920"

ce sont les lignes de code de game.py qui peut être liée à la erreur:

from os import path
img_dir = path.join(path.dirname(__file__), 'sprites')
title_screen = pygame.image.load(path.join(img_dir, 'title_screen.png'))

je pense que cela doit avoir quelque chose à voir avec pyinstaler ne pouvant pas obtenir mon dossier sprites, parce que quand j'essaie d'exécuter pyinstaller --icon=/sprites/icon.ico game.py , j'obtiens ceci:

icône de l'écran d'erreur

mais si j'utilise pyinstaller --icon=icon.ico game.py il charge l'icône très bien.

Voici mon fichier:

# -*- mode: python -*-

block_cipher = None

added_files = [
         ( '/sprites', 'sprites' ),
         ( '/music', 'music' ),
         ( 'Heavitas.ttf', '.'),
         ( 'Roboto-Light.ttf', '.'),
         ( 'high scores.csv', '.')
         ]


a = Analysis(['spec_file.py'],
             pathex=['C:UsersrodriDocumentsCodeThe Color That Fell From The Sky'],
             binaries=None,
             datas=added_files,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='spec_file',
          debug=False,
          strip=False,
          upx=True,
          console=True )
coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='spec_file')
6
demandé sur Rodrigo Nascimento 2016-12-18 02:29:35

2 réponses

enfin fait!

voici un guide rapide de ce que j'ai fait dans le cas où vous lisez ceci parce que vous avez un problème similaire. (J'ai utilisé Python 3.5.2, Pygame 1.9.2 et Pyinstaller 3.2)

Préparez votre code

comme C. _ explique sur l'autre réponse (merci), au cas où vous chargez des fichiers comme ceci:

import os
folder_path = os.path.join(path.dirname(__file__), 'folder')
some_image = pygame.image.load(os.path.join(folder_path, 'some_image.png'))

faites ceci à la place:

import sys
import os
# If the code is frozen, use this path:
if getattr(sys, 'frozen', False):
    CurrentPath = sys._MEIPASS
# If it's not use the path we're on now
else:
    CurrentPath = os.path.dirname(__file__)
# Look for the 'sprites' folder on the path I just gave you:
spriteFolderPath = os.path.join(CurrentPath, 'sprites')
# From the folder you just opened, load the image file 'some_image.png'
some_image = pygame.image.load(path.join(spriteFolderPath, 'some_image.png'))

c'est nécessaire parce que lorsque vous congelez votre code, les fichiers vont être déplacés dans un dossier différent de celui que vous avez utilisé avant. Assurez-vous de faire ça à tous les fichiers.

voici un autre exemple:

if hasattr(sys, '_MEIPASS'):  # the same logic used to set the image directory
    font = path.join(sys._MEIPASS, 'some_font.otf')  # specially useful to make a singlefile .exe
font = pygame.font.Font(font, size)
# Don't ask me the difference between hasattr and getattr because I don't know. But it works.

icône (facultatif)

si vous voulez une icône qui n'est pas la valeur par défaut de pyinstaller, vous pouvez choisir une image png et la convertir en .ico à l'aide de certains convertisseur en ligne (Google). Après ça, mets la .fichier ico sur le même dossier lorsque votre .py fichier est.

Faire le fichier de spec

à ce stade, vous devriez savoir si vous voulez un seul autonome .fichier exe ou un tas de fichiers séparés que vous zip et envoyer aux gens. Dans tous les cas, ouvrez le terminal sur le dossier où votre .le fichier py l'est.

si vous voulez un seul fichier, utilisez ceci:

pyinstaller --onefile --icon=icon_file.ico game_file.py

si vous ne le faites pas, utilisez ceci:

pyinstaller --icon=icon_file.ico game_file.py

si vous Je ne veux pas mettre l'icône maintenant, mais n'utilisez pas la partie --icon . Vous pouvez le changer plus tard. Ce que vous ne pouvez pas changer plus tard est l'option --onefile (du moins autant que je sache).

un fichier nommé game_file.spec va être créé. Il obtiendra automatiquement le nom de game_file.py. Tu peux tout gâcher s'ils ont des noms différents, alors ne sois pas créatif maintenant. Si vous choisissez un seul fichier, il devrait ressembler à ceci:

# -*- mode: python -*-

block_cipher = None

a = Analysis(['game_file.py'],
             pathex=['C:\some\path\The path where your .py and .spec are'],
             binaries=None,
             datas=None,
             hiddenimports=[],
             hookspath=[],
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)
exe = EXE(pyz,
          a.scripts,
          exclude_binaries=True,
          name='game_file',
          debug=False,
          strip=False,
          upx=True,
          console=True , icon='icon_file.ico')

si vous avez choisi avoir un tas de fichiers, vous verrez cette partie aditionnelle:

coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=False,
               upx=True,
               name='game_file')

après block_cipher = None vous allez ajouter les fichiers que votre jeu charge. Comme ceci:

added_files = [
         ( 'a folder', 'b folder' ),  # Loads the 'a folder' folder (left) and creates
                                      # an equivalent folder called 'b folder' (right)
                                      # on the destination path
         ( 'level_1/level2', 'level_2' ),  # Loads the 'level_2' folder
                                           # that's inside the 'level_1' folder
                                           # and outputs it on the root folder
         ( 'comic_sans.ttf', '.'),  # Loads the 'comic_sans.ttf' file from
                                    # your root folder and outputs it with
                                    # the same name on the same place.
         ( 'folder/*.mp3', '.')  # Loads all the .mp3 files from 'folder'.
         ]

Maintenant, vous devez ajouter " added_files ici:

a = Analysis(['game_file.py'],
                 pathex=['C:\some\path\The path where your .py and .spec are'],
                 binaries=None,
                 datas=added_files,  # Change 'None' to 'added_files' here
                                     # Leave everything else the way it is.
                 hiddenimports=[],
                 hookspath=[],
                 runtime_hooks=[],
                 excludes=[],
                 win_no_prefer_redirects=False,
                 win_private_assemblies=False,
                 cipher=block_cipher)

vous pouvez également modifier certains paramètres:

exe = EXE(pyz,
              a.scripts,
              exclude_binaries=True,
              name='game_file',  # Name of the output file. Equivalent to '--name'
                                 # Don't change it.
              debug=False,  # If True shows a debug screen on start. Equivalent to '--debug'.
              strip=False,
              upx=True,  # Compresses executable files and libraries
              # If console=True, a console screen will be shown on start up.
              # icon= is the location of the icon of the exe.
              console=True , icon='icon_file.ico')

si vous n'avez pas changé le chemin ou le nom de sortie de l'exe comme je vous ai dit de ne pas le faire sur les commentaires, nous avons juste besoin de l'exécuter et de le .exe fichier qui a été créé précédemment sera mis à jour. Entrez ceci dans la fenêtre de commande:

pyinstaller game_file.spec

rappelez-vous que game_file.spec est le fichier que nous venons d'éditer et "game_file" est un nom aléatoire que j'ai utilisé comme exemple. Notez aussi qu'il n'y a pas de --some_option parce qu'ils ne fonctionneront pas avec le fichier spec. C'est pourquoi vous devez les modifier directement dans le script. --onefile ne fonctionne pas ici et ne peut pas être fait à partir du script, c'est pourquoi Je vous ai dit de le faire avant.

vous verrez que deux dossiers ont été créés sur le même dossier où vous .le fichier spec l'est. Celui appelé 'Dist' contient le fichier exe et si vous n'avez pas utilisé --onefile , il devrait également avoir un tas d'autres fichiers que vous avez besoin de zip avec l'exe pour partager l'application avec d'autres personnes. Il y aura aussi un 'Construire' dossier mais je ne sais pas à quoi il sert, puisque vous n'avez pas besoin d'utiliser l'application.

So ce qu'il est. Ça devrait marcher pour toi.

mes erreurs quand j'ai posé la question était que je ne connaissais pas la partie sys._MEIPASS (merci encore C._), Le nom de mon fichier spec était différent de mon fichier py, j'ai utilisé '/sprites' au lieu de 'sprites' dans added_files et ne savais pas que j'étais censé exécuter le fichier spec au lieu du fichier py.

pour plus d'informations sur Pyinstaller, consultez le manuel , mais depuis il est loin d'être bon et parfois trompeur, vous êtes mieux avec Google.

12
répondu Rodrigo Nascimento 2016-12-19 03:09:27

lorsque vous compilez avec PyInstaller, tous les fichiers sont déplacés dans un répertoire différent lorsque vous exécutez votre exe . Donc, pour arriver à cet endroit, ajouter ceci au début de votre code, avant de générer des chemins

import sys

if getattr(sys, 'frozen', False): # PyInstaller adds this attribute
    # Running in a bundle
    CurrentPath = sys._MEIPASS
else:
    # Running in normal Python environment
    CurrentPath = os.path.dirname(__file__)

tous vos chemins de dossiers peuvent alors être générés à partir de votre emplacement

spriteFolderPath = path.join(CurrentPath, 'sprites') # Do the same for all your other files

ensuite, lorsque vous avez l'emplacement que vous exécutez, vous pouvez obtenir tous vos fichiers à partir de là:

title_screen = pygame.image.load(path.join(spriteFolderPath, 'title_screen.png')) # Use spriteFolderPath instead of img_dir

je vois aussi que vous avez d'autres polices/trucs, vous pouvez faire la même chose pour les charger

fontRobotoLight = pygame.font.Font(path.join(CurrentPath, 'Roboto-Light.ttf'))

pour votre icône, collez simplement un icon.ico temporaire dans votre dossier principal et tapez pyinstaller -i "icon.ico" "spec_file.spec"

enfin, comme j'ai déjà eu le même problème, je vous recommande de compiler votre exe simplement en lançant pyinstaller "spec_file.spec"

1
répondu C._ 2016-12-18 04:43:54