私は.pyゲームから.exeを作成しようとしていましたが、本当にイライラしていました。
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'))
_
_pyinstaller --icon=/sprites/icon.ico game.py
_を実行しようとすると、次のようになるので、pyinstalerが私のスプライトフォルダーを取得できないことに関係があると思います。
しかし、_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')
_
ついに完成!
同様の問題があるためにこれを読んでいる場合に備えて、私が何をしたかについての簡単なガイドを次に示します。 (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画像を選択して、オンラインコンバーター(Google it)を使用して.icoに変換できます。その後、.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.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ファイルが更新されます。コマンドウィンドウで次のように入力します。
pyinstaller game_file.spec
game_file.spec
は先ほど編集したファイルであり、「game_file」は例として使用したランダムな名前であることを忘れないでください。また、スペックファイルでは機能しないため、--some_option
がないことに注意してください。これが、スクリプトで直接変更する必要がある理由です。 --onefile
もここでは機能せず、スクリプト内からも実行できません。そのため、以前にそうするように言っています。
.specファイルと同じフォルダに2つのフォルダが作成されたことがわかります。 「Dist」と呼ばれるものにはexeファイルが含まれており、--onefile
を使用しなかった場合、他の人とアプリケーションを共有するためにexeとともにZipする必要のある他のファイルもたくさんあるはずです。 「Buid」フォルダもありますが、アプリケーションを使用するために必要がないため、その目的はわかりません。
これでおしまいです。それはあなたのために働くはずです。
質問したときの間違いは、sys._MEIPASS
の部分がわからなかった(C._に感謝)。スペックファイルの名前がpyファイルとは異なり、代わりに'/sprites'
を使用しました。の'sprites'
のadded_files
と、pyファイルの代わりにspecファイルを実行することになっていることを知りませんでした。
Pyinstallerの詳細については、 manual を参照してください。ただし、これはあまりよくなく、時には誤解を招く可能性があるため、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"
と入力します
最後に、以前同じ問題があったので、pyinstaller "spec_file.spec"
を実行するだけでexe
をコンパイルすることをお勧めします