2-5 PyInstallerの導入
同人誌について
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで288ページの本になります。ぜひ、こちらもご購入ください(2024-03-10:ver1.0.3 に更新)。
PyInstallerとは
『PyInstaller』は、『Python』で書いたプログラムを1つにパッケージして、exe化するツールです。
開発したゲームは、exeファイルにして配布したいです。『Python』のプロジェクトをexe化するツールはいくつかあるのですが、ここでは情報が多く、定番の『PyInstaller』を使います。
PyInstallerの導入
『PyInstaller』をグローバル環境に導入する際は`pip install pyinstaller`コマンドを使います。今回は、仮想環境に導入して使いたいので、CLI環境でプロジェクトのディレクトリに移動して、次のコマンドを実行します。
.venv\Scripts\activate
pip install pyinstaller
deactivate
インストールは3分程度かかります。「.venv」ディレクトリにファイルが導入されます。「.venv」ディレクトリのサイズは51.2MBになりました。前の操作では39.0MBだったので、12.2MBほど増えました。
仮想環境内に正しくインストールできたか確認しましょう。次のコマンドを実行します。
.venv\Scripts\activate
pip list
deactivate
表示されるパッケージ一覧に「pyinstaller」が含まれていれば正しくインストールできています。
注意すべき点
『PyInstaller』を使う上では、注意すべき点がいくつかあります。
1つ目の注意すべき点は、仮想環境についてです。仮想環境で開発したプログラムを正しくexe化するには、『PyInstaller』も仮想環境にインストールする必要があります。そして、exe化を仮想環境内でおこなう必要があります。
2つ目の注意すべき点は、出力される場所です。exe化をおこなうと「dist」ディレクトリ内に出力されます。ルート直下の「main.py」をexe化したときは、次のようなファイル構成になります。
root/
dist/
main.exe
main.py
「main.py」から、相対パスでファイルを読み込んでいる場合は、出力したexeの場所を次のように移動する必要があります。
root/
main.exe
3つ目の注意すべき点は`__file__`のあつかいです。『Python』では、現在実行しているプログラムのファイルのパスが`__file__`に入っています。3.9以降の環境では、この`__file__`には絶対パスが入っています。
『PyInstaller』でexe化したプログラムでは、この`__file__`のパスを使うことは避けた方がよいです。『PyInstaller』で作ったexeファイルを実行すると、exeファイルとは別の場所のパスになります。
`print(__file__)`で出力すると`C:\Users<ユーザー名>\AppData\Local\Temp_<一時的な文字列>\main.py`と出力されます。この場所に実行に必要なDLLなどが展開されています(「main.py」は展開されていません)。
この問題の回避方法は、次々節で解説します。
実行ファイルを作る
次のコマンドを実行します。
.venv\Scripts\activate
pyinstaller main.py --onefile --noconsole
deactivate
コマンドを実行すると、「build」ディレクトリと「dist」ディレクトリができます。「build」ディレクトリはビルドに利用されたファイルが入っているので不要です。「dist」ディレクトリ内に「main.exe」が作成されます。実行ファイルの名前は、プログラムのエントリー ポイントのファイル名です。
デバッグ時は`--noconsole`を消すとよいです。CLI環境のウィンドウが表示され、標準出力の内容を確かめられます。
アイコンを付けたいときは、コマンドに`--icon=src/icon.ico`のように相対パスでアイコン ファイルの場所を書きます。
相対パスの問題の回避方法
開発中の「main.py」の絶対パスは`__file__`で得られます。exe化したときの「main.exe」の絶対パスは`sys.executable`で得られます。exe化の判定は`getattr(sys, 'frozen', False)`が`True`を返すかでおこなえます。
開発時と出力時のディレクトリの構成例を示します。
root/
dist/ …… 出力時
main.exe
src/ …… 開発時
main.py
audio/
font/
image/
次にプログラムを示します。exe化の判定をおこない、パスを調整して、「root」をCWD(カレント ワーキング ディレクトリ)にして実行する例です。
import os, sys
app_path = __file__
if getattr(sys, 'frozen', False): app_path = sys.executable
app_dir = os.path.dirname(os.path.dirname(app_path))
os.chdir(app_dir)
print("@cwd@", os.getcwd())
CLI環境で「src/main.py」を実行して出力したCWDと、exe化して「dist/main.exe」を実行したCWDを確かめます。1行目と3行目で、同じパスが出力されます。
.venv\Scripts\activate
pyinstaller src/main.py --onefile
dist\main.exe
python src/main.py
deactivate
同人誌について
この連載は、同人誌『PythonとPygameで作る レトロ風RPG 全コード』を一部抜粋して編集したものです。
同人誌本編には、ゲーム本体のソースコードや、各種のサンプルコード、Windowsで実行できるEXEファイルが付属しています。PDFで288ページの本になります。ぜひ、こちらもご購入ください(2024-03-10:ver1.0.3 に更新)。
このnoteの記事と、Webページに一部抜粋版を掲載しています。
技術系同人誌など まとめページ
この記事が気に入ったらサポートをしてみませんか?