Pygame 使用 Pyinstaller 制作 .exe 后未加载 png
Pygame not loading png after making .exe with Pyinstaller
我一直在尝试从我的 .py 游戏中制作一个 .exe,这真的很令人沮丧。
我正在使用 Python 3.5.2、Pygame 1.9.2 和 Pyinstaller 3.2。
游戏 运行 与 .py 完全一样,但在我输入 pyinstaller --debug game.py
后,.exe 已构建并且我 运行 它,我得到以下信息:
debug screen
这些是 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 无法获取我的 sprites 文件夹有关,因为当我尝试 运行 pyinstaller --icon=/sprites/icon.ico game.py
时,我得到了这个:
icon error screen
但是如果我使用 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:\Users\rodri\Documents\Code\The 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')
当您使用 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
我也看到你还有其他的fonts/stuff,你也可以这样做来加载它们
fontRobotoLight = pygame.font.Font(path.join(CurrentPath, 'Roboto-Light.ttf'))
对于您的图标,只需在您的主文件夹中粘贴一个临时 icon.ico
并键入
pyinstaller -i "icon.ico" "spec_file.spec"
最后,因为我之前遇到过同样的问题,我建议你通过 运行ning pyinstaller "spec_file.spec"
简单地编译你的 exe
终于成功了!
以下是我所做的快速指南,以防您因遇到类似问题而阅读本文。 (我使用了 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 它)。之后,将 .ico 文件放在你的 .py 文件所在的同一文件夹中。
制作规范文件
此时您应该知道您是想要一个独立的 .exe 文件还是要压缩并发送给其他人的一堆单独的文件。在任何情况下,在您的 .py 文件所在的文件夹中打开终端。
如果你想要单个文件,使用这个:
pyinstaller --onefile --icon=icon_file.ico game_file.py
如果你不这样做,使用这个:
pyinstaller --icon=icon_file.ico game_file.py
如果您现在不想设置图标,请不要使用 --icon
部分。您可以稍后更改它。您以后不能更改的是 --onefile 选项(至少据我所知)。
将创建一个名为 game_file.spec 的文件。它将自动从 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 文件将被更新。在命令 window:
中输入
pyinstaller game_file.spec
请记住,game_file.spec
是我们刚刚编辑的文件,'game_file' 是我用作示例的随机名称。另请注意,没有 --some_option
因为它们不适用于规范文件。这就是为什么您必须直接在脚本中更改它们的原因。 --onefile
在这里也不起作用,不能从脚本中完成,这就是我之前告诉你这样做的原因。
您会看到在 .spec 文件所在的同一文件夹中创建了两个文件夹。名为 'Dist' 的文件包含 exe 文件,如果您没有使用 --onefile
,它还应该包含一堆其他文件,您需要将这些文件与 exe 一起压缩以便与其他人共享应用程序.还会有一个 'Buid' 文件夹,但我不知道它的用途,因为您不需要它来使用该应用程序。
就是这样。它应该适合你。
我做题时的错误是我不知道sys._MEIPASS
部分(再次感谢C._),我的spec文件的名称与我的py文件不同,我在 added_files
中使用 '/sprites'
而不是 'sprites'
并且不知道我应该 运行 spec 文件而不是 py 文件。
有关 Pyinstaller 的更多信息,请查看 manual,但由于它远非好用且有时会产生误导,您最好使用 Google。
我一直在尝试从我的 .py 游戏中制作一个 .exe,这真的很令人沮丧。
我正在使用 Python 3.5.2、Pygame 1.9.2 和 Pyinstaller 3.2。
游戏 运行 与 .py 完全一样,但在我输入 pyinstaller --debug game.py
后,.exe 已构建并且我 运行 它,我得到以下信息:
debug screen
这些是 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 无法获取我的 sprites 文件夹有关,因为当我尝试 运行 pyinstaller --icon=/sprites/icon.ico game.py
时,我得到了这个:
icon error screen
但是如果我使用 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:\Users\rodri\Documents\Code\The 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')
当您使用 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
我也看到你还有其他的fonts/stuff,你也可以这样做来加载它们
fontRobotoLight = pygame.font.Font(path.join(CurrentPath, 'Roboto-Light.ttf'))
对于您的图标,只需在您的主文件夹中粘贴一个临时 icon.ico
并键入
pyinstaller -i "icon.ico" "spec_file.spec"
最后,因为我之前遇到过同样的问题,我建议你通过 运行ning pyinstaller "spec_file.spec"
exe
终于成功了!
以下是我所做的快速指南,以防您因遇到类似问题而阅读本文。 (我使用了 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 它)。之后,将 .ico 文件放在你的 .py 文件所在的同一文件夹中。
制作规范文件
此时您应该知道您是想要一个独立的 .exe 文件还是要压缩并发送给其他人的一堆单独的文件。在任何情况下,在您的 .py 文件所在的文件夹中打开终端。
如果你想要单个文件,使用这个:
pyinstaller --onefile --icon=icon_file.ico game_file.py
如果你不这样做,使用这个:
pyinstaller --icon=icon_file.ico game_file.py
如果您现在不想设置图标,请不要使用 --icon
部分。您可以稍后更改它。您以后不能更改的是 --onefile 选项(至少据我所知)。
将创建一个名为 game_file.spec 的文件。它将自动从 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 文件将被更新。在命令 window:
中输入pyinstaller game_file.spec
请记住,game_file.spec
是我们刚刚编辑的文件,'game_file' 是我用作示例的随机名称。另请注意,没有 --some_option
因为它们不适用于规范文件。这就是为什么您必须直接在脚本中更改它们的原因。 --onefile
在这里也不起作用,不能从脚本中完成,这就是我之前告诉你这样做的原因。
您会看到在 .spec 文件所在的同一文件夹中创建了两个文件夹。名为 'Dist' 的文件包含 exe 文件,如果您没有使用 --onefile
,它还应该包含一堆其他文件,您需要将这些文件与 exe 一起压缩以便与其他人共享应用程序.还会有一个 'Buid' 文件夹,但我不知道它的用途,因为您不需要它来使用该应用程序。
就是这样。它应该适合你。
我做题时的错误是我不知道sys._MEIPASS
部分(再次感谢C._),我的spec文件的名称与我的py文件不同,我在 added_files
中使用 '/sprites'
而不是 'sprites'
并且不知道我应该 运行 spec 文件而不是 py 文件。
有关 Pyinstaller 的更多信息,请查看 manual,但由于它远非好用且有时会产生误导,您最好使用 Google。