【完全保存版】Python GUI→exe化で必ず出る25のエラーと解決法
はじめに - なぜエラーが出るのか
PythonでGUIアプリを作成し、PyInstallerでexe化しようとすると、必ずと言っていいほどエラーに遭遇します。私自身も初めてexe化に挑戦したとき、10種類以上のエラーと格闘し、解決に丸2日かかった経験があります。
本記事では、PyInstallerを使ったexe化で必ず出る25のエラーパターンとその解決法を網羅的にまとめました。
PyInstallerでエラーが出やすい3つの理由
-
依存関係の自動検出が不完全
- PyInstallerは静的解析でモジュールを検出しますが、動的インポートや隠れた依存関係は見逃します
-
実行環境の違い
- 開発環境では動くのに、exeにすると相対パスやファイル配置が変わるため動かなくなります
-
ライブラリ固有の問題
- pandas、numpy、OpenCVなど、特定ライブラリは特別な設定が必要です
この記事の使い方
- エラーメッセージで検索: 目次から該当するエラーに即ジャンプ
- 予防チェックリスト: 開発前に確認して事前にエラーを防ぐ
- フローチャート: エラーの切り分け方法を図解
対象読者・前提環境
- Python初心者〜中級者
- tkinter/PySimpleGUI等でGUI作成経験あり
- Windows 10/11(一部macOS対応も記載)
- Python 3.8以上
- PyInstaller 5.0以上
目次
環境構築編(エラー1-5)
- pip install PyInstaller失敗
- Pythonバージョン非対応
- パス設定の問題
- 仮想環境認識エラー
- 権限不足エラー
ビルド実行編(エラー6-13)
- ModuleNotFoundError(基本パターン)
- ModuleNotFoundError(サブモジュール)
- FileNotFoundError(画像・データファイル)
- ImportError(隠れた依存関係)
- RecursionError
- UnicodeDecodeError
- specファイル構文エラー
- アイコンファイル形式エラー
実行時編(エラー14-20)
- ハンドル無効エラー
- DLLロードエラー
- 相対パス問題
- 一時ファイル展開エラー
- ウイルス対策ソフト誤検知
- 起動時クラッシュ
- GUI表示崩れ
特殊ライブラリ編(エラー21-25)
- pandas/numpy MKL問題
- OpenCV依存関係
- PyQt/PySide問題
- Pillow画像パス問題
- matplotlib表示エラー
環境構築編(エラー1-5)
エラー1: pip install PyInstaller失敗
症状
pip install pyinstaller
ERROR: Could not install packages due to an OSError
原因
- Windows Defenderがインストールをブロック
- ネットワーク制限(企業環境)
- pipのバージョンが古い
解決法
解決策1: pipを最新化
python -m pip install --upgrade pip
pip install pyinstaller
解決策2: Windows Defenderを一時的に無効化
- Windowsセキュリティを開く
- ウイルスと脅威の防止 → 設定の管理
- リアルタイム保護を一時的にオフ
- インストール後、必ずオンに戻す
解決策3: ユーザーディレクトリにインストール
pip install --user pyinstaller
エラー2: Pythonバージョン非対応
症状
pyinstaller main.py
ERROR: This version of PyInstaller requires Python 3.8+
原因
- PyInstaller 5.0以降はPython 3.7以下非対応
- 複数のPythonバージョンが混在
解決法
解決策1: Pythonバージョン確認
python --version
# Python 3.7.x の場合は3.8以上にアップグレード
解決策2: 仮想環境で正しいバージョンを指定
# Python 3.10で仮想環境作成
python3.10 -m venv myenv
myenv\Scripts\activate # Windows
source myenv/bin/activate # macOS/Linux
解決策3: pyenvで複数バージョン管理
pyenv install 3.10.0
pyenv local 3.10.0
エラー3: パス設定の問題
症状
'pyinstaller' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
原因
- PyInstallerがシステムPATHに登録されていない
- 仮想環境のScriptsフォルダがPATHにない
解決法
解決策1: フルパスで実行
# Windows
python -m PyInstaller main.py
# または
C:\Users\YourName\AppData\Local\Programs\Python\Python310\Scripts\pyinstaller.exe main.py
解決策2: 環境変数PATHに追加(Windows)
- システムの詳細設定 → 環境変数
- Path変数を編集
- 以下を追加:
C:\Users\YourName\AppData\Local\Programs\Python\Python310\Scripts
解決策3: 仮想環境を有効化してから実行
.venv\Scripts\activate
pyinstaller main.py
エラー4: 仮想環境認識エラー
症状
pyinstaller main.py
# グローバル環境のライブラリが使われてしまう
# または、ImportError: No module named 'xxx'
原因
- 仮想環境がアクティブになっていない
- 複数の仮想環境が混在
解決法
解決策1: 仮想環境を確実にアクティブ化
# Windows
.venv\Scripts\activate
# プロンプトに(.venv)が表示されることを確認
# macOS/Linux
source .venv/bin/activate
解決策2: 使用中のPythonパスを確認
where python # Windows
which python # macOS/Linux
# 仮想環境のパスが表示されることを確認
解決策3: deactivateしてから再度activate
deactivate
.venv\Scripts\activate
pip list # インストール済みライブラリを確認
エラー5: 権限不足エラー
症状
pyinstaller main.py
PermissionError: [Errno 13] Permission denied: 'dist/main.exe'
原因
- 前回ビルドしたexeが実行中
- distフォルダが読み取り専用
- ウイルス対策ソフトがファイルをロック
解決法
解決策1: 実行中のexeを終了
# タスクマネージャーでmain.exeを終了
# または
taskkill /F /IM main.exe # Windows
解決策2: dist/buildフォルダを削除してから実行
rmdir /s /q dist build # Windows
rm -rf dist build # macOS/Linux
pyinstaller main.py --clean
解決策3: 管理者権限で実行
- コマンドプロンプトを右クリック → 管理者として実行
- その後pyinstallerコマンドを実行
ビルド実行編(エラー6-13)
エラー6: ModuleNotFoundError(基本パターン)
症状
# ビルドは成功するが、exeを実行すると
ModuleNotFoundError: No module named 'tkinter'
ModuleNotFoundError: No module named 'PIL'
ModuleNotFoundError: No module named 'requests'
原因
- PyInstallerがモジュールを自動検出できていない
- 動的インポート(importlib等)を使用している
- サブモジュールの検出漏れ
解決法
解決策1: specファイルのhiddenimportsに追加
まず、specファイルを生成:
pyinstaller main.py --onefile
# main.specが生成される
main.specを編集:
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[
'tkinter',
'PIL',
'PIL.Image',
'requests',
], # ここに追加
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
再ビルド:
pyinstaller main.spec --clean
解決策2: コマンドオプションで指定
pyinstaller main.py --onefile --hidden-import=PIL --hidden-import=requests
解決策3: よく漏れるモジュール一覧
hiddenimports=[
# GUI関連
'tkinter',
'tkinter.ttk',
'tkinter.filedialog',
'tkinter.messagebox',
# 画像処理
'PIL',
'PIL.Image',
'PIL.ImageTk',
'PIL.ImageDraw',
# データ処理
'pandas',
'numpy',
'openpyxl',
'xlrd',
# Web関連
'requests',
'urllib3',
'certifi',
]
エラー7: ModuleNotFoundError(サブモジュール)
症状
# 特定のサブモジュールだけエラー
ModuleNotFoundError: No module named 'pandas.io.excel'
ModuleNotFoundError: No module named 'plotly.validators.layout'
原因
- 親モジュールは検出されているが、サブモジュールが漏れている
- plotly、pandas等は内部構造が複雑で検出漏れが多発
解決法
解決策1: サブモジュールを個別指定
hiddenimports=[
'pandas',
'pandas.io',
'pandas.io.excel',
'pandas.io.excel._xlrd',
'pandas.io.excel._openpyxl',
]
解決策2: ワイルドカード的に全サブモジュール追加(plotlyの例)
# 全サブモジュールを取得するスクリプト
import pkgutil
import plotly
def get_all_submodules(package):
submodules = []
for importer, modname, ispkg in pkgutil.walk_packages(
path=package.__path__,
prefix=package.__name__ + '.',
):
submodules.append(modname)
return submodules
plotly_modules = get_all_submodules(plotly)
print(plotly_modules)
# この結果をhiddenimportsにコピー
解決策3: よく問題になるサブモジュール一覧
hiddenimports=[
# pandas関連
'pandas.io.formats.excel',
'pandas.plotting._matplotlib',
# plotly関連(大量)
'plotly.validators',
'plotly.validators.layout',
'plotly.graph_objs',
# sklearn関連
'sklearn.utils._cython_blas',
'sklearn.neighbors.typedefs',
'sklearn.tree._utils',
]
エラー8: FileNotFoundError(画像・データファイル)
症状
# exeを実行すると
FileNotFoundError: [Errno 2] No such file or directory: 'icon.png'
FileNotFoundError: [Errno 2] No such file or directory: 'data/config.json'
原因
- 画像やデータファイルがexeに同梱されていない
- 相対パスの基準がexe実行時とPython実行時で異なる
解決法
解決策1: specファイルのdatasに追加
a = Analysis(
['main.py'],
datas=[
('icon.png', '.'), # (元のパス, exe内の配置先)
('data/config.json', 'data'),
('images/*.png', 'images'), # フォルダごと
],
)
解決策2: コマンドオプションで指定
pyinstaller main.py --onefile --add-data "icon.png;." --add-data "data;data"
# Windowsは ; 、macOS/Linuxは : を使用
解決策3: 実行時パスを動的に取得するコード
import sys
import os
def resource_path(relative_path):
"""PyInstallerでexe化した際のリソースパスを取得"""
try:
# PyInstallerで作成された一時フォルダ
base_path = sys._MEIPASS
except Exception:
# 通常のPython実行時
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# 使用例
icon_path = resource_path('icon.png')
image = Image.open(icon_path)
解決策4: フォルダ構造を保持して配置
プロジェクト/
├─ main.py
├─ images/
│ ├─ icon.png
│ └─ logo.png
└─ data/
└─ config.json
# specファイルで
datas=[
('images', 'images'),
('data', 'data'),
]
# コード内で
icon_path = resource_path('images/icon.png')
エラー9: ImportError(隠れた依存関係)
症状
ImportError: DLL load failed while importing _imaging: 指定されたモジュールが見つかりません。
ImportError: cannot import name 'soft_unicode' from 'markupsafe'
原因
- ライブラリが内部で別のライブラリに依存している
- DLLファイルが不足している
- バージョン不整合
解決法
解決策1: 依存関係を明示的にインストール
# Pillowの例
pip install pillow
pip install pillow --force-reinstall
# 依存関係を確認
pip show pillow
解決策2: 問題のあるライブラリを再インストール
pip uninstall markupsafe
pip install markupsafe==2.0.1 # 安定バージョンを指定
解決策3: hiddenimportsに依存ライブラリを追加
hiddenimports=[
'PIL._tkinter_finder', # Pillow + tkinterの場合
'pkg_resources.py2_warn', # setuptools関連
]
解決策4: バイナリファイルを明示的に含める
a = Analysis(
['main.py'],
binaries=[
('C:/path/to/library.dll', '.'),
],
)
エラー10: RecursionError
症状
RecursionError: maximum recursion depth exceeded
# ビルド中に発生
原因
- PyInstaller内部で再帰処理が深すぎる
- 循環インポートがある
- 複雑なライブラリ依存関係
解決法
解決策1: 再帰回数上限を増やす
main.pyの先頭に追加:
import sys
sys.setrecursionlimit(5000) # デフォルトは1000
解決策2: specファイルで設定
import sys
sys.setrecursionlimit(5000)
a = Analysis(
['main.py'],
# 以下通常通り
)
解決策3: 循環インポートを解消
# 悪い例
# module_a.py
import module_b
# module_b.py
import module_a # 循環インポート
# 良い例:必要な箇所でのみインポート
# module_b.py
def some_function():
import module_a # 関数内でインポート
module_a.do_something()
エラー11: UnicodeDecodeError
症状
UnicodeDecodeError: 'cp932' codec can't decode byte 0x99 in position 123
# ビルド時または実行時に発生
原因
- ソースコードやデータファイルに日本語が含まれる
- Windowsのデフォルトエンコーディング(cp932)と不一致
解決法
解決策1: ファイル先頭にエンコーディング宣言
# -*- coding: utf-8 -*-
import tkinter as tk
# 以下コード
解決策2: ファイル読み込み時にエンコーディング指定
# 悪い例
with open('data.txt', 'r') as f:
data = f.read()
# 良い例
with open('data.txt', 'r', encoding='utf-8') as f:
data = f.read()
解決策3: PyInstallerコマンドでエンコーディング指定
set PYTHONIOENCODING=utf-8
pyinstaller main.py --onefile
解決策4: 環境変数を設定
import os
os.environ['PYTHONIOENCODING'] = 'utf-8'
エラー12: specファイル構文エラー
症状
pyinstaller main.spec
SyntaxError: invalid syntax
原因
- specファイル編集時の構文ミス
- カンマ、カッコの対応ミス
- インデントの誤り
解決法
解決策1: 基本的なspecファイル構造を確認
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=None)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False, # GUIの場合False
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
解決策2: よくあるミス
# ミス1: カンマ忘れ
hiddenimports=[
'tkinter'
'PIL' # ← カンマがない!
]
# 正しい
hiddenimports=[
'tkinter',
'PIL',
]
# ミス2: パスのエスケープ
datas=[
('C:\images\icon.png', '.') # ← \が特殊文字として解釈される
]
# 正しい
datas=[
(r'C:\images\icon.png', '.'), # rをつける
# または
('C:/images/icon.png', '.'), # スラッシュ使用
]
解決策3: specファイルを再生成
# 既存のspecを削除
del main.spec
# 再生成
pyinstaller main.py --onefile --noconsole
# 再度編集
エラー13: アイコンファイル形式エラー
症状
pyinstaller main.py --icon=icon.png
IOError: cannot identify image file 'icon.png'
原因
- PNG形式を指定している(icoファイルが必要)
- アイコンファイルが壊れている
- ファイルサイズが大きすぎる
解決法
解決策1: PNGをICOに変換
from PIL import Image
# PNG画像を読み込み
img = Image.open('icon.png')
# ICOファイルとして保存
img.save('icon.ico', format='ICO', sizes=[(256, 256)])
解決策2: オンラインツールで変換
解決策3: 複数サイズのアイコンを含める
from PIL import Image
img = Image.open('icon.png')
img.save('icon.ico', format='ICO', sizes=[
(16, 16),
(32, 32),
(48, 48),
(64, 64),
(256, 256)
])
解決策4: specファイルでアイコン指定
exe = EXE(
# ...
icon='icon.ico', # .icoファイルを指定
# ...
)
実行時編(エラー14-20)
エラー14: ハンドル無効エラー
症状
OSError: [WinError 6] ハンドルが無効です。
# --noconsole + --onefile の組み合わせで発生
原因
-
--noconsole
と--onefile
を同時使用時、subprocessがstdinを見失う - テキスト処理ライブラリ(pytesseract等)で頻発
解決法
解決策1: subprocess呼び出しにstdin=DEVNULL追加
エラーが出ているライブラリの該当ファイルを修正:
# 例: pytesseractのtesseract.py
import subprocess
# 修正前
proc = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
# 修正後
proc = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.DEVNULL # これを追加
)
解決策2: 自分のコードでsubprocessを使っている場合
import subprocess
# 必ずstdin=subprocess.DEVNULLを指定
result = subprocess.run(
['command', 'arg'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.DEVNULL # 追加
)
解決策3: --onedirモードで回避
# --onefileを使わない
pyinstaller main.py --noconsole
# distフォルダ内に複数ファイルが生成されるが、エラーは出ない
エラー15: DLLロードエラー
症状
ImportError: DLL load failed: 指定されたモジュールが見つかりません。
# numpy、scipy、OpenCV等で頻発
原因
- 必要なDLLファイルがexeに同梱されていない
- Visual C++ 再頒布可能パッケージが未インストール
- 32bit/64bitの不一致
解決法
解決策1: Visual C++ 再頒布可能パッケージをインストール
配布先PCで必要:
- Visual C++ 2015-2022 再頒布可能パッケージ
- ダウンロード: https://aka.ms/vs/17/release/vc_redist.x64.exe
解決策2: DLLを明示的に同梱
import numpy
import os
# numpyのDLLパスを取得
numpy_path = numpy.__path__[0]
dll_path = os.path.join(numpy_path, '.libs')
# specファイルで
binaries=[
(dll_path, '.libs'),
]
解決策3: Anaconda環境の場合
# conda環境から必要なDLLをコピー
# C:\Users\YourName\anaconda3\Library\bin\*.dll
解決策4: Pythonビット数確認
import platform
print(platform.architecture())
# ('64bit', 'WindowsPE') であることを確認
エラー16: 相対パス問題
症状
# 開発時は動くが、exeにすると
FileNotFoundError: [Errno 2] No such file or directory: './data/config.json'
原因
- カレントディレクトリがexe実行時とPython実行時で異なる
- PyInstallerは一時フォルダに展開してから実行する
解決法
解決策1: 実行ファイルの場所を基準にする
import sys
import os
def get_base_path():
"""実行ファイルのディレクトリを取得"""
if getattr(sys, 'frozen', False):
# exe化されている場合
return os.path.dirname(sys.executable)
else:
# Python実行の場合
return os.path.dirname(os.path.abspath(__file__))
# 使用例
base_path = get_base_path()
config_path = os.path.join(base_path, 'data', 'config.json')
with open(config_path, 'r') as f:
config = json.load(f)
解決策2: リソースパス取得関数(エラー8の再掲)
def resource_path(relative_path):
"""PyInstallerの一時フォルダまたは開発時のパスを返す"""
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# 使用例
config_path = resource_path('data/config.json')
解決策3: 絶対パスは避ける
# 悪い例
image = Image.open('C:/Users/YourName/project/icon.png')
# 良い例
image = Image.open(resource_path('icon.png'))
エラー17: 一時ファイル展開エラー
症状
# exeを起動すると
Failed to execute script 'main' due to unhandled exception!
[Errno 28] No space left on device
原因
-
--onefile
で作成したexeは起動時に一時フォルダへ展開 - 一時フォルダの容量不足
- ウイルス対策ソフトが展開をブロック
解決法
解決策1: 一時フォルダをクリーンアップ
# Windowsの一時フォルダ
%TEMP%
C:\Users\YourName\AppData\Local\Temp
# _MEIから始まるフォルダを削除
解決策2: --onedirモードを使用
# 一時展開が不要になる
pyinstaller main.py --noconsole
# distフォルダごと配布
解決策3: 展開先を指定
# specファイルで
exe = EXE(
# ...
runtime_tmpdir='./temp', # 展開先を指定
# ...
)
解決策4: ディスク容量確保
- Cドライブの空き容量を確認
- 不要ファイルを削除
- 一時フォルダを別ドライブに変更
エラー18: ウイルス対策ソフト誤検知
症状
# exeを実行すると
Windows Defender: トロイの木馬として検出されました
# または起動後すぐに強制終了
原因
- PyInstallerで作成したexeは、ウイルス対策ソフトに誤検知されやすい
- 特に
--onefile
モードは自己展開型のため疑われる - UPX圧縮を使うとさらに誤検知率が上がる
解決法
解決策1: Windows Defenderの除外設定
1. Windowsセキュリティを開く
2. ウイルスと脅威の防止 → 設定の管理
3. 除外 → 除外の追加または削除
4. exeファイルまたはフォルダを追加
解決策2: UPX圧縮を無効化
pyinstaller main.py --onefile --noupx
解決策3: コード署名証明書を取得
# 有料だが信頼性向上
# DigiCert、Sectigo等から購入
# signtool.exeで署名
signtool sign /f certificate.pfx /p password main.exe
解決策4: --onedirモードで配布
# 誤検知されにくい
pyinstaller main.py --noconsole
解決策5: VirusTotalでスキャン結果を確認
- https://www.virustotal.com/
- 複数のウイルス対策ソフトでスキャン
- 誤検知なら各ベンダーに報告可能
エラー19: 起動時クラッシュ
症状
# exeをダブルクリックしても一瞬で消える
# またはエラーダイアログなしで終了
原因
- 起動直後のエラーがコンソール非表示で見えない
- 初期化処理での例外
- 必須ファイルの不足
解決法
解決策1: --consoleモードでデバッグ
# コンソールを表示してエラー確認
pyinstaller main.py --onefile --console
# エラーメッセージが表示されるようになる
解決策2: ログファイル出力を追加
import logging
import sys
import os
# ログ設定
log_file = os.path.join(os.path.dirname(sys.executable), 'app.log')
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_file, encoding='utf-8'),
logging.StreamHandler()
]
)
# メイン処理をtry-exceptで囲む
try:
logging.info('アプリケーション起動')
# メイン処理
main()
except Exception as e:
logging.exception('エラーが発生しました')
raise
解決策3: 段階的にコメントアウトして原因特定
def main():
print("Step 1") # ここまで実行されるか確認
# import heavy_library # 一旦コメントアウト
print("Step 2")
# gui_window = create_gui() # 一旦コメントアウト
print("Step 3")
# run_main_logic() # 一旦コメントアウト
解決策4: 例外ハンドラーでメッセージボックス表示
import tkinter as tk
from tkinter import messagebox
import traceback
def show_error(e):
"""エラーをGUIで表示"""
root = tk.Tk()
root.withdraw()
error_msg = f"エラーが発生しました:\n\n{str(e)}\n\n{traceback.format_exc()}"
messagebox.showerror("エラー", error_msg)
root.destroy()
try:
main()
except Exception as e:
show_error(e)
エラー20: GUI表示崩れ
症状
# exeを実行すると
# - ボタンが見えない
# - 画像が表示されない
# - フォントが変わる
# - レイアウトがずれる
原因
- 画像ファイルのパスが通っていない
- フォントファイルが不足
- DPIスケーリングの影響
- tkinterのバージョン差異
解決法
解決策1: 画像パスを動的取得に変更
# 悪い例
icon = PhotoImage(file='icon.png')
# 良い例
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
icon = PhotoImage(file=resource_path('icon.png'))
解決策2: DPI対応
import ctypes
# Windows 10/11でDPI認識を有効化
try:
ctypes.windll.shcore.SetProcessDpiAwareness(1)
except:
pass
root = tk.Tk()
解決策3: フォント明示指定
# システムフォントに依存しない
import tkinter.font as tkFont
# 明示的にフォント指定
default_font = tkFont.Font(family='メイリオ', size=10)
label = tk.Label(root, text='テスト', font=default_font)
解決策4: レイアウト固定
# サイズ可変を避ける
root = tk.Tk()
root.geometry('800x600')
root.resizable(False, False) # サイズ変更不可
# 絶対座標でウィジェット配置
button.place(x=100, y=50, width=200, height=40)
特殊ライブラリ編(エラー21-25)
エラー21: pandas/numpy MKL問題
症状
# exeファイルが300MB以上になる
# または
ImportError: DLL load failed: 指定されたモジュールが見つかりません。
原因
- pandas/numpyはIntel MKL(数学演算ライブラリ)を内包
- MKLだけで100-200MB以上
- 不要な場合も強制的に含まれる
解決法
解決策1: MKLを除外(軽量化)
specファイルを編集:
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
# 通常の設定
)
# MKL除外コード追加
def remove_mkl(binaries_list):
"""MKL関連ファイルを除外"""
return [
(dest, src, kind)
for dest, src, kind in binaries_list
if not dest.startswith('mkl')
]
a.binaries = remove_mkl(a.binaries)
pyz = PYZ(a.pure, a.zipped_data)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='main',
# 以下通常通り
)
解決策2: より詳細なMKL除外
def remove_from_list(input_list, keywords):
"""キーワードを含むファイルを除外"""
output_list = []
for item in input_list:
name, src, kind = item
should_exclude = False
for keyword in keywords:
if keyword in name.lower():
should_exclude = True
break
if not should_exclude:
output_list.append(item)
return output_list
# 除外キーワード
exclude_keywords = ['mkl', 'libopenblas', 'libblas', 'liblapack']
a.binaries = remove_from_list(a.binaries, exclude_keywords)
解決策3: numpy-baseをインストール(軽量版)
pip uninstall numpy
pip install numpy-base # MKLなしバージョン
# ただし計算速度は低下
解決策4: 実測比較
MKL込み: 約320MB
MKL除外: 約35MB
削減率: 約89%
エラー22: OpenCV依存関係
症状
ModuleNotFoundError: No module named 'cv2'
# または
ImportError: DLL load failed while importing cv2
原因
- OpenCVは依存関係が複雑
- 複数のDLLファイルが必要
- バージョンによって必要ファイルが異なる
解決法
解決策1: hiddenimportsに追加
hiddenimports=[
'cv2',
'numpy',
'numpy.core',
]
解決策2: OpenCVのDLLを明示的に含める
import cv2
import os
cv2_path = os.path.dirname(cv2.__file__)
# specファイルで
binaries=[
(os.path.join(cv2_path, 'opencv_ffmpeg*.dll'), '.'),
]
datas=[
(cv2_path, 'cv2'),
]
解決策3: opencv-python-headlessを使用
pip uninstall opencv-python
pip install opencv-python-headless
# GUI機能なし、軽量版
解決策4: PyInstallerのhookファイル作成
# hook-cv2.py を作成
from PyInstaller.utils.hooks import collect_data_files, collect_dynamic_libs
datas = collect_data_files('cv2')
binaries = collect_dynamic_libs('cv2')
specファイルで指定:
a = Analysis(
['main.py'],
hookspath=['./hooks'], # hook-cv2.pyがあるフォルダ
)
エラー23: PyQt/PySide問題
症状
ModuleNotFoundError: No module named 'PyQt5.QtCore'
# または
ImportError: DLL load failed: 指定されたプロシージャが見つかりません。
原因
- PyQt5/PySide2は巨大なライブラリ
- プラグインファイルが多数必要
- Qt特有の依存関係
解決法
解決策1: hiddenimportsに全モジュール追加
hiddenimports=[
'PyQt5',
'PyQt5.QtCore',
'PyQt5.QtGui',
'PyQt5.QtWidgets',
'PyQt5.sip',
]
解決策2: PyQt5専用のhookを使用
# PyInstallerは自動でPyQt5を検出するはずだが、
# 手動で指定する場合
pyinstaller main.py --hidden-import=PyQt5 --hidden-import=PyQt5.sip
解決策3: プラグインフォルダを含める
import PyQt5
import os
qt_plugin_path = os.path.join(os.path.dirname(PyQt5.__file__), 'Qt5', 'plugins')
# specファイルで
datas=[
(qt_plugin_path, 'PyQt5/Qt5/plugins'),
]
解決策4: 軽量化したい場合
# 不要なQtモジュールを除外
a = Analysis(
['main.py'],
excludes=[
'PyQt5.QtWebEngine', # Webエンジン不要なら
'PyQt5.QtBluetooth',
'PyQt5.Qt3D',
],
)
エラー24: Pillow画像パス問題
症状
PIL.UnidentifiedImageError: cannot identify image file
# または
FileNotFoundError: [Errno 2] No such file or directory: 'image.png'
原因
- 画像ファイルがexeに含まれていない
- パス指定が相対パス
- PIL内部のフォントファイルが不足
解決法
解決策1: 画像ファイルをdatasに追加
# specファイルで
datas=[
('images/*.png', 'images'),
('images/*.jpg', 'images'),
]
解決策2: リソースパス取得
from PIL import Image
import sys
import os
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# 使用例
image_path = resource_path('images/sample.png')
img = Image.open(image_path)
解決策3: PILフォントファイルの問題
# カスタムフォント使用時
from PIL import ImageFont
# 悪い例
font = ImageFont.truetype('arial.ttf', 20)
# 良い例
font_path = resource_path('fonts/arial.ttf')
font = ImageFont.truetype(font_path, 20)
# specファイルで
datas=[
('fonts/*.ttf', 'fonts'),
]
解決策4: 画像をBase64エンコードして埋め込み
import base64
from io import BytesIO
from PIL import Image
# 画像をBase64に変換(事前処理)
with open('icon.png', 'rb') as f:
img_data = base64.b64encode(f.read()).decode()
# コード内に埋め込み
IMG_DATA = 'iVBORw0KGgoAAAANSUhEUgAA...' # Base64文字列
# 使用時
img_bytes = base64.b64decode(IMG_DATA)
img = Image.open(BytesIO(img_bytes))
エラー25: matplotlib表示エラー
症状
ImportError: No module named 'matplotlib.backends.backend_tkagg'
# または
RuntimeError: Could not find the matplotlib data files
原因
- matplotlibのバックエンドモジュールが欠落
- データファイル(フォント等)が不足
- tkinterバックエンドの依存関係
解決法
解決策1: hiddenimportsに追加
hiddenimports=[
'matplotlib',
'matplotlib.backends.backend_tkagg',
'matplotlib.backends.backend_agg',
'matplotlib.figure',
]
解決策2: matplotlibのデータファイルを含める
import matplotlib
import os
mpl_data_path = os.path.join(matplotlib.__path__[0], 'mpl-data')
# specファイルで
datas=[
(mpl_data_path, 'matplotlib/mpl-data'),
]
解決策3: バックエンドを明示指定
import matplotlib
matplotlib.use('TkAgg') # または 'Agg'
import matplotlib.pyplot as plt
解決策4: Agグバックエンドで画像保存のみ
# GUI表示せず、画像ファイル保存のみ
import matplotlib
matplotlib.use('Agg') # GUIなし
import matplotlib.pyplot as plt
plt.plot([1, 2, 3], [4, 5, 6])
plt.savefig('output.png')
# plt.show() は使わない
解決策5: 完全なhiddenimports
hiddenimports=[
'matplotlib',
'matplotlib.backends',
'matplotlib.backends.backend_tkagg',
'matplotlib.backends.backend_agg',
'matplotlib.figure',
'matplotlib.pyplot',
'tkinter',
'tkinter.filedialog',
]
エラー解決フローチャート
エラー診断3ステップ
ステップ1: エラー発生タイミングの特定
# Q1: pipインストール時?
→ 環境構築編(エラー1-5)
# Q2: pyinstallerコマンド実行時?
→ ビルド実行編(エラー6-13)
# Q3: exeファイル実行時?
→ 実行時編(エラー14-20)
ステップ2: エラーメッセージのキーワード検索
"ModuleNotFoundError" → エラー6, 7
"FileNotFoundError" → エラー8, 24
"DLL load failed" → エラー15, 21, 22
"ハンドル無効" → エラー14
"RecursionError" → エラー10
ステップ3: 使用ライブラリの確認
# requirements.txtを確認
pandas → エラー21
numpy → エラー21
opencv-python → エラー22
PyQt5 → エラー23
pillow → エラー24
matplotlib → エラー25
予防チェックリスト20項目
開発前チェック(7項目)
- Python 3.8以上をインストール済み
-
仮想環境を作成して開発を開始
python -m venv .venv .venv\Scripts\activate
-
requirements.txtで依存関係を管理
pip freeze > requirements.txt
- ファイルパスは全て相対パスで記述
-
画像・データファイルは専用フォルダに整理
project/ ├─ main.py ├─ images/ └─ data/
-
コード内の日本語はUTF-8で保存
# -*- coding: utf-8 -*-
- subprocessを使う場合はstdin=DEVNULL指定
ビルド前チェック(8項目)
-
仮想環境がアクティブか確認
where python # 仮想環境のパスが表示されるか
-
不要なライブラリをアンインストール
pip list # 使っていないライブラリを確認 pip uninstall [不要なライブラリ]
-
PyInstallerを最新版に更新
pip install --upgrade pyinstaller
- アイコンファイルは.ico形式か確認
-
前回のdist/buildフォルダを削除
rmdir /s /q dist build
-
--consoleモードで一度ビルドしてエラー確認
pyinstaller main.py --console
- エラーが出た場合はspecファイルを編集
- hiddenimports/datasを適切に設定
配布前チェック(5項目)
- 別のPCで動作確認(可能なら)
- Windows Defenderでスキャン
-
README.txtを同梱
- 使い方
- 必要な環境
- トラブルシューティング
- Visual C++ 再頒布可能パッケージの案内
-
バージョン番号をファイル名に含める
MyApp_v1.0.0.exe
よくある質問TOP10
Q1: exeファイルが500MBを超えてしまう
A: MKL除外、仮想環境最適化で大幅削減可能
# specファイルでMKL除外(エラー21参照)
def remove_mkl(binaries_list):
return [(d, s, k) for d, s, k in binaries_list if not d.startswith('mkl')]
a.binaries = remove_mkl(a.binaries)
# 実測: 320MB → 35MB(約90%削減)
Q2: exe起動に30秒以上かかる
A: --onedirモードに変更で劇的に改善
# --onefileは起動時に展開するため遅い
pyinstaller main.py --onefile # 起動30秒
# --onedirは展開不要で高速
pyinstaller main.py # 起動3秒
Q3: 他のPCで「DLLがない」と言われる
A: Visual C++ 再頒布可能パッケージをインストール
配布先PCで必要:
https://aka.ms/vs/17/release/vc_redist.x64.exe
Q4: Windows Defenderがウイルスと判定
A: 除外設定、または--noupxオプション
pyinstaller main.py --onefile --noupx
Q5: 画像が表示されない
A: リソースパス取得関数を使用(エラー8, 16参照)
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
img = Image.open(resource_path('icon.png'))
Q6: エラーメッセージが見えない
A: --consoleモードで実行、またはログ出力
pyinstaller main.py --console
import logging
logging.basicConfig(filename='app.log', level=logging.DEBUG)
Q7: pandas/numpyでエラーが出る
A: MKL問題またはhiddenimports不足
# specファイルで
hiddenimports=[
'pandas',
'pandas.io.formats.excel',
'numpy',
'numpy.core',
]
# MKL除外(エラー21参照)
Q8: macOS/Linuxでも動かしたい
A: 各OS環境で個別にビルドが必要
# Windows用exeはWindowsでビルド
# macOS用appはmacOSでビルド
# Linux用はLinuxでビルド
# クロスコンパイルは不可
Q9: アップデート配布方法は?
A: GitHub Releaseまたはバージョン管理機能実装
# 簡易バージョンチェック
import requests
CURRENT_VERSION = '1.0.0'
UPDATE_URL = 'https://api.github.com/repos/user/repo/releases/latest'
def check_update():
response = requests.get(UPDATE_URL)
latest = response.json()['tag_name']
if latest > CURRENT_VERSION:
print(f'新バージョン{latest}があります')
Q10: specファイルとは?編集必須?
A: ビルド設定ファイル。エラー時のみ編集
# 初回は自動生成される
pyinstaller main.py
# エラーが出たら編集
# main.spec を開いてhiddenimports等を追加
# 次回から
pyinstaller main.spec --clean
トラブルシューティング実践例
実例1: pandas使用ツールのエラー完全解決
状況: Excelファイル処理ツールをexe化したい
遭遇エラー:
- ModuleNotFoundError: pandas.io.excel
- exeが320MB
- 起動に25秒かかる
解決手順:
# ステップ1: hiddenimports追加
hiddenimports=[
'pandas',
'pandas.io.excel._xlrd',
'pandas.io.excel._openpyxl',
'openpyxl',
'xlrd',
]
# ステップ2: MKL除外で軽量化
def remove_mkl(binaries):
return [(d, s, k) for d, s, k in binaries if 'mkl' not in d.lower()]
a.binaries = remove_mkl(a.binaries)
# ステップ3: --onedirで高速化
pyinstaller main.spec # --onefileを外す
# 結果:
# ファイルサイズ: 320MB → 45MB
# 起動時間: 25秒 → 3秒
実例2: 画像処理アプリの完全修正
状況: Pillow + OpenCVで画像編集ツール
遭遇エラー:
- FileNotFoundError: icon.png
- ImportError: cv2 DLL load failed
- GUI表示崩れ
解決手順:
# main.py
import sys
import os
from PIL import Image
import cv2
import tkinter as tk
def resource_path(relative_path):
"""リソースパス取得"""
try:
base_path = sys._MEIPASS
except:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
# 画像読み込み修正
icon_path = resource_path('images/icon.png')
img = Image.open(icon_path)
# DPI対応
import ctypes
try:
ctypes.windll.shcore.SetProcessDpiAwareness(1)
except:
pass
# specファイル
datas=[
('images', 'images'),
]
hiddenimports=[
'cv2',
'PIL',
'PIL._tkinter_finder',
]
# OpenCVのDLL追加
import cv2
cv2_path = os.path.dirname(cv2.__file__)
binaries=[
(os.path.join(cv2_path, '*.dll'), '.'),
]
# 結果: すべてのエラー解消
まとめ - エラーゼロへのロードマップ
重要ポイント再確認
-
仮想環境は必須
- 無駄なライブラリ同梱を防ぐ
- ファイルサイズ大幅削減
-
相対パスは動的取得
- resource_path関数を活用
- sys._MEIP
エラーはわからないと本当に辛いものでした。少しでも多くのみなさんのひとつのエラーに役に立てれば幸いです。
今後ともよろしくお願いします。