Pygame не загружает png после создания.exe с Pyinstaller
Я пытался сделать .exe от моего .py игра, и это было очень неприятно.
я использую Python 3.5.2, Pygame 1.9.2 и Pyinstaller 3.2.
игра работает отлично, как .py, но после того, как я войду pyinstaller --debug game.py
действие .exe построен, и я запускаю его, я получаю следующее:
Это строки кода из game.py это может быть связано с ошибкой:
from os import path
img_dir = path.join(path.dirname(__file__), 'sprites')
title_screen = pygame.image.load(path.join(img_dir, 'title_screen.png'))
Я думаю, что это должно быть что-то связано с тем, что pyinstaler не может получить мою папку спрайтов, потому что когда я пытаюсь запустить pyinstaller --icon=/sprites/icon.ico game.py
, Я получаю это:
но если я использую pyinstaller --icon=icon.ico game.py
он загружает значок просто отлично.
вот мой файл спецификации:
# -*- 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')
2 ответов
наконец-то!
вот краткое руководство о том, что я сделал, если Вы читаете это, потому что у вас есть аналогичная проблема. (Я использовал Python 3.5.2, Pygame 1.9.2 и Pyinstaller 3.2)
подготовьте код
как C._ объясняет другой ответ (Спасибо), в случае, если вы загружаете файлы, как это:
import os
folder_path = os.path.join(path.dirname(__file__), 'folder')
some_image = pygame.image.load(os.path.join(folder_path, 'some_image.png'))
вместо этого:
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'))
это необходимо, потому что, когда вы заморозите свой код, файлы будут переместился в другую папку, чем та, которую вы использовали раньше. Убедитесь, что вы сделали это со всеми файлами.
вот еще один пример:
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.
(необязательный)
если вы хотите значок, который не pyinstaller по умолчанию, вы можете выбрать png изображение и преобразовать его.ico с помощью некоторого онлайн-конвертера (Google it). После этого, положите .ICO файл в той же папке, где ваш .файл py есть.
сделайте файл спецификации
в этот момент Вы следует знать, если вы хотите один автономный .exe файл или куча отдельных файлов, которые вы будете zip и отправить людям. В любом случае, откройте терминал на папке, где ваш.файл py есть.
если вы хотите один файл, используйте этот:
pyinstaller --onefile --icon=icon_file.ico game_file.py
если вы этого не делаете, используйте это:
pyinstaller --icon=icon_file.ico game_file.py
если вы не хотите устанавливать значок сейчас, просто не используйте --icon
часть. Вы можете изменить его позже. Что вы не можете изменить это параметр --onefile (по крайней мере, насколько мне известно).
файл с именем game_file.будет создана спецификация. Он автоматически получит имя от game_file.py - ... Вы можете испортить его, если у них разные имена,так что не творите сейчас. Если вы выбрали один файл, он должен выглядеть так:
# -*- 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')
если вы решили иметь кучу файлов, вы увидите в этом фильме часть:
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='game_file')
после block_cipher = None
вы добавите файлы, которые загружает ваша игра. Вот так:
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'.
]
теперь вы должны добавить "added_files" здесь:
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)
вы также можете изменить некоторые параметры:
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')
если вы не изменили путь или выходное имя exe, как я сказал вам не в комментариях, нам просто нужно запустить его и .exe-файл, который был ранее создан, будет обновлен. Введите это в командном окне:
pyinstaller game_file.spec
помните, что game_file.spec
это файл, который мы только что отредактировали, а "game_file" - случайное имя, которое я использовал в качестве примера. Заметить также что нет --some_option
потому что они не будут работать с файлом спецификации. Вот почему вы должны изменить их непосредственно в скрипт. --onefile
также не работает здесь и не может быть сделано из сценария, поэтому я сказал вам сделать это раньше.
вы увидите, что были созданы в той же папке, где две папки .Spec-файл. Тот, который называется "Dist", содержит exe-файл, и если вы не использовали --onefile
, он также должен иметь кучу других файлов, которые вам нужно сжать вместе с exe, чтобы поделиться приложением с другими людьми. Там также будет папка "Buid", но я не знаю, для чего это, так как вам не нужно использовать приложение.
так вот оно что. Это должно сработать для тебя.
мои ошибки, когда я сделал вопрос в том, что я не знаю sys._MEIPASS
часть (еще раз спасибо C._), имя моего файла спецификации отличалось от моего файла py, я использовал '/sprites'
вместо 'sprites'
на added_files
и не знал, что я должен выполнить Spec-файл вместо файл py.
для получения дополнительной информации о Pyinstaller, взгляните на руководство, но поскольку это далеко не хорошо и иногда вводит в заблуждение, вам лучше с Google.
при компиляции с помощью PyInstaller все файлы перемещаются в другой каталог при запуске exe
. Итак, чтобы добраться до этого места, добавьте это в начало своего кода, прежде чем создавать пути
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__)
все ваши пути к папкам могут быть сгенерированы из вашего местоположения
spriteFolderPath = path.join(CurrentPath, 'sprites') # Do the same for all your other files
затем, когда у вас есть место, в котором вы выполняете, вы можете получить все свои файлы оттуда:
title_screen = pygame.image.load(path.join(spriteFolderPath, 'title_screen.png')) # Use spriteFolderPath instead of img_dir
я тоже вижу, что у вас есть другие шрифты / вещи, вы можете сделать то же самое, чтобы загрузить их
fontRobotoLight = pygame.font.Font(path.join(CurrentPath, 'Roboto-Light.ttf'))
для вашего значка просто вставьте временный icon.ico
в главной папке и типа
pyinstaller -i "icon.ico" "spec_file.spec"
наконец, я была такая же проблема раньше, я рекомендую вам составить свой exe
просто работает pyinstaller "spec_file.spec"