使用 Pyinstaller 制作 .exe 后 Pygame 未加载 png [英] Pygame not loading png after making .exe with Pyinstaller

查看:34
本文介绍了使用 Pyinstaller 制作 .exe 后 Pygame 未加载 png的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试从我的 .py 游戏中制作一个 .exe,这真的很令人沮丧.

I've been trying to make an .exe from my .py game and it's been really frustrating.

我使用的是 Python 3.5.2、Pygame 1.9.2 和 Pyinstaller 3.2.

I'm using Python 3.5.2, Pygame 1.9.2 and Pyinstaller 3.2.

游戏以 .py 格式完美运行,但在我输入 pyinstaller --debug game.py 后,构建了 .exe 并运行它,我得到以下信息:

The game is running perfectly as .py, but after I enter pyinstaller --debug game.py, the .exe is built and I run it, I get the following:

调试屏幕

这些是 game.py 中可能与错误相关的代码行:

These are the lines of code from game.py that may be related to the error:

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 时,我明白了:

I think it must have something to do with pyinstaler not being able to get my sprites folder, because when I try to run pyinstaller --icon=/sprites/icon.ico game.py, I get this:

图标错误画面

但是如果我使用 pyinstaller --icon=icon.ico game.py 它加载图标就好了.

But if I use pyinstaller --icon=icon.ico game.py it loads the icon just fine.

这是我的规范文件:

# -*- 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')

推荐答案

终于搞定了!

这里是我所做的快速指南,以防您因为遇到类似问题而阅读本文.(我使用了 Python 3.5.2、Pygame 1.9.2 和 Pyinstaller 3.2)

Here's a quick guide of what I did in case you're reading this because you have a similar problem. (I used Python 3.5.2, Pygame 1.9.2 and Pyinstaller 3.2)

就像 C._ 解释了另一个答案(谢谢),以防您加载这样的文件:

Like C._ explains on the other answer (thanks), in case you are loading you files like this:

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'))

这是必要的,因为当您冻结代码时,文件将被移动到与您之前使用的文件夹不同的文件夹中.确保对所有文件都执行此操作.

It's needed because when you freeze your code, the files are gonna be moved to a different folder than the one you used before. Make sure you do this to all the files.

这是另一个例子:

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.之后,将 .ico 文件放在 .py 文件所在的文件夹中.

Icon (optional)

If you want an icon that's not pyinstaller's default, you can choose a png image and convert it to .ico using some online converter (Google it). After that, put the .ico file on the same folder where your .py file is.

此时您应该知道您是想要一个独立的 .exe 文件还是一堆单独的文件,您将压缩并发送给其他人.无论如何,请在 .py 文件所在的文件夹中打开终端.

At this point you should know if you want a single self contained .exe file or a bunch of separate files that you will zip and send to people. In any case, open the terminal on the folder where your .py file is.

如果您想要单个文件,请使用:

If you want a single file, use this:

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

如果您不这样做,请使用此:

If you don't, use this:

pyinstaller --icon=icon_file.ico game_file.py

如果您现在不想设置图标,请不要使用 --icon 部分.您可以稍后更改它.您以后不能更改的是 --onefile 选项(至少据我所知).

If you don't want to set the icon now, just don't use the --icon part. You can change it later. What you can't change later is the --onefile option (at least as far as I know).

一个名为 game_file.spec 的文件将被创建.它将自动从 game_file.py 获取名称.如果他们有不同的名字,你可以把它搞砸,所以现在不要有创意.如果您选择了单个文件,它应该如下所示:

A file named game_file.spec will be created. It will automatically get the name from game_file.py. You can mess it up if they have different names, so don't get creative now. If you chose a single file, it should look like this:

# -*- 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')

如果你选择了一堆文件,你会看到这个附加部分:

If you chose to have a bunch of files, you'll see this aditional part:

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

block_cipher = None 之后,您将添加游戏加载的文件.像这样:

After block_cipher = None you're gonna add the files your game loads. Like this:

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'.
         ]

现在您必须在此处添加已添加的文件":

Now you have to add 'added_files' here:

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)

您还可以更改一些设置:

You can also change some settings:

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 文件将被更新.在命令窗口中输入:

If you didn't change the path or the output name of the exe like I told you not to on the comments, we just need to run it and the .exe file that was previously created will be updated. Enter this on the command window:

pyinstaller game_file.spec

请记住,game_file.spec 是我们刚刚编辑的文件,'game_file' 是我用作示例的随机名称.另请注意,没有 --some_option 因为它们不适用于规范文件.这就是您必须直接在脚本中更改它们的原因.--onefile 在这里也不起作用,也不能在脚本中完成,这就是我之前告诉你要这样做的原因.

Remember that game_file.spec is the file we just edited and 'game_file' is a random name I used as an example. Also notice that there's no --some_option because they won't work with the spec file. This is why you have to change them directly in the script. --onefile also doesn't work here and can't be done from within the script, that's why I told you to do it before.

您会看到在 .spec 文件所在的同一文件夹中创建了两个文件夹.名为Dist"的文件包含 exe 文件,如果您没有使用 --onefile,它还应该有一堆其他文件,您需要将这些文件与 exe 一起压缩以共享应用程序和其他人.还会有一个Buid"文件夹,但我不知道它的用途,因为您不需要它来使用该应用程序.

You will se that two folders were created on the same folder where you .spec file is. The one called 'Dist' contains the exe file and if you didn't use --onefile, it should also have a bunch of other files that you need to zip along with the exe to share the application with other people. There will also be a 'Buid' folder but I don't know what it's for, since you don't need it to use the application.

就是这样.它应该适合你.

So this is it. It should work for you.

我提出问题时的错误是我不知道 sys._MEIPASS 部分(再次感谢 C._),我的规范文件的名称与我的 py 文件不同,我在 added_files 中使用了 '/sprites' 而不是 'sprites' 并且不知道我应该运行规范文件而不是py 文件.

My mistakes when I made the question was that I didn't know the sys._MEIPASS part (thanks again C._), the name of my spec file was different from my py file, I used '/sprites' instead of 'sprites' in added_files and didn't know I was supposed to run the spec file instead of the py file.

有关 Pyinstaller 的更多信息,请查看手册,但由于它离很好,但有时会产生误导,您最好使用 Google.

For more information on Pyinstaller, take a look at the manual, but since it's far from good and sometimes misleading, you're better off with Google.

这篇关于使用 Pyinstaller 制作 .exe 后 Pygame 未加载 png的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆