Pygame not loading png after making .exe with Pyinstaller
我一直在尝试从我的.py游戏中制作一个.exe,这确实令人沮丧。
我正在使用Python 3.5.2,Pygame 1.9.2和Pyinstaller 3.2。
该游戏以.py完美运行,但是输入
调试屏幕
这些是来自game.py的代码行,可能与该错误有关:
1 2 3 | 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文件夹有关,因为当我尝试运行
图标错误屏幕
但是,如果我使用
这是我的规格文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # -*- 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\ odri\\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') |
终于做到了!
如果您因为有类似问题而正在阅读本文,这是我的快速指南。 (我使用了Python 3.5.2,Pygame 1.9.2和Pyinstaller 3.2)
准备你的代码
就像C._在另一个答案上的解释(谢谢)一样,如果您正在加载这样的文件:
1 2 3 | import os folder_path = os.path.join(path.dirname(__file__), 'folder') some_image = pygame.image.load(os.path.join(folder_path, 'some_image.png')) |
而是这样做:
1 2 3 4 5 6 7 8 9 10 11 12 | 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')) |
这是必需的,因为在冻结代码时,文件将被移到与以前使用的文件夹不同的文件夹中。确保对所有文件都执行此操作。
这是另一个例子:
1 2 3 4 | 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图像,然后使用一些在线转换器(Google将该图像转换为.ico)。之后,将.ico文件放在.py文件所在的文件夹中。
制作规格文件
在这一点上,您应该知道要压缩的单个.exe文件还是一堆单独的文件,然后将其发送给人们。无论如何,请在您的.py文件所在的文件夹中打开终端。
如果只需要一个文件,请使用以下命令:
1 | pyinstaller --onefile --icon=icon_file.ico game_file.py |
如果不这样做,请使用以下命令:
1 | pyinstaller --icon=icon_file.ico game_file.py |
如果您不想现在设置图标,请不要使用
将创建一个名为game_file.spec的文件。它将自动从game_file.py获得名称。如果它们的名称不同,则可以将其弄乱,所以不要立即发挥创意。如果选择单个文件,则它应如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # -*- 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') |
如果选择一堆文件,则会看到以下附加部分:
1 2 3 4 5 6 7 | coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, name='game_file') |
在
1 2 3 4 5 6 7 8 9 10 11 12 | 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":
1 2 3 4 5 6 7 8 9 10 11 12 | 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) |
您还可以更改一些设置:
1 2 3 4 5 6 7 8 9 10 11 | 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文件。在命令窗口中输入以下内容:
1 | pyinstaller game_file.spec |
请记住,
您会发现在.spec文件所在的同一文件夹上创建了两个文件夹。名为" Dist"的文件包含exe文件,如果您不使用
就是这样。它应该为您工作。
当我问这个问题时,我的错误是我不知道
有关Pyinstaller的更多信息,请查看手册,但是由于它远非易事,有时甚至会引起误解,因此使用Google最好。
使用PyInstaller进行编译时,在运行
1 2 3 4 5 6 7 8 | 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__) |
然后可以从您的位置生成所有文件夹路径
1 | spriteFolderPath = path.join(CurrentPath, 'sprites') # Do the same for all your other files |
然后,当您确定要执行的位置时,可以从此处获取所有文件:
1 | title_screen = pygame.image.load(path.join(spriteFolderPath, 'title_screen.png')) # Use spriteFolderPath instead of img_dir |
我还看到您还有其他字体/材料,您可以执行相同的操作来加载它们
1 | fontRobotoLight = pygame.font.Font(path.join(CurrentPath, 'Roboto-Light.ttf')) |
对于您的图标,只需在主文件夹中粘贴一个临时
最后,由于我之前遇到过相同的问题,我建议您仅通过运行