Python / コンパイルする方法とEXEファイルの作り方

PythonコードをWindowsのEXEとして配布するには、PyInstallerでプログラムとPython実行環境、必要なライブラリをまとめられます。py_compileで生成する.pycはPython用バイトコードであり、独立したWindows実行ファイルではありません。まずフォルダー形式で動作を確認し、必要に応じて単一EXEにすると問題を切り分けやすくなります。

バイトコードのコンパイルとEXEのパッケージ化

py_compileはソースをバイトコードファイルに変換します。PyInstallerのパッケージ化はインタープリターと依存ファイルを集めて配布用アプリを作ります。通常のPythonコードをC経由で最適化したネイティブ機械語へ変換する処理とは異なり、実行速度の向上やソースの安全な秘匿を自動的に実現するものではありません。

成果物はOSとアーキテクチャに依存します。Windows EXEはWindowsでビルドします。Linuxでオプションを指定するだけでWindows用に変換できるクロスコンパイラーとは考えないでください。対応環境と使用パッケージの互換性を確認します。

Windowsの作業フォルダーと仮想環境を準備

Python 3とpipを導入したWindowsのPowerShellを使います。新しい作業フォルダーでターミナルを開き、次の順に実行します。py -3が認識されない場合、最初の行をPython実行ファイルのパス、またはそのPythonを指すpythonコマンドに置き換えます。

py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install "pyinstaller==6.22.3"
.\.venv\Scripts\python.exe -m PyInstaller --version

.venvはこの作業の仮想環境です。その中のPythonを直接呼ぶため、有効化スクリプトやPowerShell実行ポリシーの変更は不要です。例ではPyInstaller 6.22.3に固定しており、別の版を選ぶ場合は互換性とオプションを再確認します。インストールに成功し、最後の出力が6.22.3であることを確かめます。

アプリが追加パッケージを使う場合は同じ仮想環境に依存関係を導入します。無関係なパッケージが多いグローバル環境では、解析や成果物の管理が複雑になることがあります。

完全な例を保存してバイトコードを作る

作業フォルダーにUTF-8のhello.pyを作成します。

print("Hello, packaging!")
Hello, packaging!

まずソースを実行し、上の文字列が表示されることを確認します。

.\.venv\Scripts\python.exe hello.py

バイトコードへのコンパイルだけを試す場合は次を実行します。

.\.venv\Scripts\python.exe -m py_compile hello.py

成功時は通常、表示なしで__pycache__にhello.cpython-312.pycのようなファイルができます。版を示す部分はPythonによって変わります。拡張子をEXEに変えても独立実行にはならず、互換性のあるPython実行環境が必要です。

フォルダー形式でビルドして配布

作業フォルダーで次の2行を順に実行します。ビルド成功後に実行コマンドを入力します。

.\.venv\Scripts\python.exe -m PyInstaller --onedir --name hello-folder hello.py
.\dist\hello-folder\hello-folder.exe

出力はHello, packaging!です。EXEと補助ファイルを含むdist\hello-folder全体を配布します。EXEだけでは必要なライブラリが不足する場合があります。補助ファイルは_internal以下に置かれることがあり、詳細な構成はパッケージやオプションによって異なります。

buildは中間ファイルと診断情報、hello-folder.specはビルド設定です。利用者へ渡すのはdist内の成果物であり、buildや.venvではありません。各オプションはPyInstallerの使用方法を参照します。

単一EXEにまとめる

フォルダー形式が動いたら同じソースを単一ファイルにします。別名にすることで両方の成果物を比較できます。

.\.venv\Scripts\python.exe -m PyInstaller --onefile --name hello-single hello.py
.\dist\hello-single.exe

dist\hello-single.exeを1ファイルとして配布でき、出力は同じです。起動時に内部ファイルを一時領域へ展開するため、起動が遅くなる場合があります。容量や速度の優位を一律に保証せず、実際のアプリで判断します。

このコンソール例には--windowedを付けません。コンソールを使わないGUIでは検討できますが、print()やinput()のプログラムに無条件で付けると入出力やエラー確認が難しくなります。原因を調べずに管理者実行やセキュリティソフトの無効化を基本対処にしないでください。

フォルダー形式と単一ファイル形式は、WindowsのPython 3.12.14とPyInstaller 6.22.3で生成し出力を確認しました。同じホストのコンソール例の検証であり、Pythonのない別PCやGUIの動作確認ではありません。

テキストや画像などのデータを含める

コードが読むファイルがすべて自動収集されるとは限りません。UTF-8のmessage.txtにHello from bundled data!を1行で保存します。同じ場所にhello_data.pyを次の内容で作成します。

from pathlib import Path

message = Path(__file__).resolve().with_name("message.txt")
print(message.read_text(encoding="utf-8").strip())
Hello from bundled data!

ソース実行と次のビルド実行で同じ文字列になることを確かめます。__file__基準のパスはターミナルの現在のフォルダーに依存せず、バンドル内部のファイルを探す方法として使えます。

.\.venv\Scripts\python.exe -m PyInstaller --onefile --name hello-data --add-data "message.txt:." hello_data.py
.\dist\hello-data.exe

--add-data "message.txt:."はファイルをバンドルの最上位に含めます。現行文書の区切りはコロンです。古いOS別の区切り文字の例を混在させず、データ同梱の規則とコードのパスを合わせます。単一ファイルから展開した内部データへの変更は永続保存には向きません。利用者の設定や出力は別の書き込み可能なユーザーパスに保存します。

失敗時の確認と配布前の点検

  1. EXEがすぐ閉じる場合は、ダブルクリックではなくPowerShellで実行してエラーを読みます。ソース自体が同じ仮想環境で動くか先に確認します。
  2. モジュール不足なら導入環境と実際のimport方法を確認します。動的importには追加収集設定が必要な場合があります。build\名前\warn-名前.txtも確認しますが、すべての警告が致命的とは限りません。
  3. データ不足なら--add-dataの配置先とコードのパスを照合します。フォルダー形式に戻してファイルや実行経路を見ると原因を絞れます。
  4. 配布先と同じOS・アーキテクチャで機能を試します。Pythonのない別環境、ファイルアクセス、外部プログラム依存、同梱パッケージの再配布条件も確認します。

診断方法はPyInstallerのトラブルシューティングを参照します。ビルドと実行のコマンドを区別し、再現用ソース・パッケージの版・エラーを記録すると原因調査に役立ちます。