0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonコードを実行ファイル化 (PyInstaller)

Posted at

PyInstaller ライブラリを利用して Python コードを実行形式に変換する手順を以下に記載します。
発生したエラーと対処方法についても備忘録として残しておきます。

動作環境

  • Windows 11 / macOS 15.7.2
  • Python 3.12.3
  • PyInstaller 6.16.0
  • uv 0.9.9 (Homebrew 2025-11-12)

サンプルコード

キーを押すとカウントする簡単なプログラムです。

git clone https://github.com/tamaohome/practice-pyinstaller.git

ディレクトリ構成

practice-pyinstaller
├─ main.spec
└─ app/
   ├─ __init__.py
   ├─ counter.py
   └─ main.py
  • main.spec は PyInstaller 実行時に自動生成される (後述)
  • __init__.py は空ファイル
  • pyproject.toml などプロジェクト固有のファイルは省略

app/main.py

from readchar import readkey
from app.counter import Counter


def main():
    counter = Counter()
    print("任意のキーでカウント, Rキーでリセット, Qキーで終了")

    while True:
        print(f"\r{counter.format_count()}", end="", flush=True)
        k = readkey()
        if k == "r":
            counter.reset()
        elif k == "q":
            break
        else:
            counter.count_up()

    print("\n終了")


if __name__ == "__main__":
    main()

app/counter.py

class Counter:
    MAX_COUNT = 10000  # 最大カウント
    DIGITS = len(str(MAX_COUNT - 1))  # 表示桁数

    def __init__(self):
        self._count = 0

    def count_up(self):
        self._count = (self._count + 1) % self.MAX_COUNT

    def reset(self):
        self._count = 0

    def format_count(self):
        return f"カウント: [{self._count:0{self.DIGITS}d}]"

PyInstaller による変換手順

以下の手順ではプロジェクト管理に uv を使用します。

(1) pyinstaller ライブラリを追加

以下のコマンドでライブラリを追加します。

uv add --dev pyinstaller

確認のため where コマンドを実行します。

where pyinstaller

pyinstaller がプロジェクト内の仮想環境 .venv/ 以下に存在していれば OK

(2) PyInstaller の初回実行

以下のコマンドを実行します。引数にはエントリーポイントの Python パスを指定します(今回は app/main.py)。

pyinstaller app/main.py

実行後、プロジェクトルートに main.spec(PyInstallerの設定ファイル)が作成されます。

main.spec
# -*- mode: python ; coding: utf-8 -*-


a = Analysis(
    ['app/main.py'],
    pathex=[],
    binaries=[],
    datas=[],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)
pyz = PYZ(a.pure)

exe = EXE(
    pyz,
    a.scripts,
    a.binaries,
    a.datas,
    [],
    name='main',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    upx_exclude=[],
    runtime_tmpdir=None,
    console=True,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)

(3) 設定ファイル main.spec の編集

使用するライブラリによっては起動時にエラーが発生するため、以下のようにライブラリ名を追加します。

# -*- mode: python ; coding: utf-8 -*-

+ from PyInstaller.utils.hooks import copy_metadata


a = Analysis(
    ['app/main.py'],
    pathex=[],
    binaries=[],
-    datas=[],
+    datas=copy_metadata("readchar"),
    hiddenimports=[],
    ...

(4) PyInstaller を実行

引数に設定ファイルを指定します。

pyinstaller main.spec

PyInstaller の実行が完了すると dist/ に実行ファイルが作成されます。

ビルドエラーの原因および対処方法

その1

PyInstaller 実行ファイル起動時に以下のエラーが発生

Traceback (most recent call last):
  File "importlib/metadata/__init__.py", line 397, in from_name
StopIteration

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "main.py", line 1, in <module>
  File "pyimod02_importers.py", line 457, in exec_module
  File "readchar/__init__.py", line 6, in <module>
  File "importlib/metadata/__init__.py", line 889, in version
  File "importlib/metadata/__init__.py", line 862, in distribution
  File "importlib/metadata/__init__.py", line 399, in from_name
importlib.metadata.PackageNotFoundError: No package metadata was found for readchar
[PYI-26825:ERROR] Failed to execute script 'main' due to unhandled exception!

原因:

インポートするライブラリによっては PyInstaller に対応していないため、上記のようなエラーが発生します。

対処方法:

datas= に使用するライブラリを明記します(本稿では修正済み)。

main.spec

from PyInstaller.utils.hooks import collect_metadata

a = Analysis(
    ['app/main.py'],
    pathex=[],
    binaries=[],
    datas=collect_metadata("readchar"),
    ...

その2

PyInstaller 実行ファイル起動時に ImportError が発生

Traceback (most recent call last):
  File "main.py", line 2, in <module>
ImportError: attempted relative import with no known parent package
[PYI-46653:ERROR] Failed to execute script 'main' due to unhandled exception!

原因・対処方法:

相対インポートの使用が原因のため、絶対インポートに変更します(本稿では修正済み)。

-from .counter import Counter
+from app.counter import Counter

その3

PyInstaller 実行ファイル起動時に ModuleNotFoundError が発生

Traceback (most recent call last):
  File "main.py", line 2, in <module>
ModuleNotFoundError: No module named 'app'
[PYI-47123:ERROR] Failed to execute script 'main' due to unhandled exception!

原因・対処方法:

app/__init__.py が存在しない場合、app ディレクトリがモジュールと認識されずにエラーとなります。

ディレクトリ内に __init__.py(空ファイルでOK)を置くことで解決できます。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?