概要
Windows 環境で Python アプリを PyInstaller で exe 化する際に、
-
pip-system-certsを導入したあと PyInstaller がビルドエラーで落ちる -
ビルドは通っても、exe 実行時に
[SSL: CERTIFICATE_VERIFY_FAILED]が発生する -
.pyで実行すると問題が出ない
という 複合的で分かりづらいトラブルに遭遇した。
本記事では、
-
何が壊れていたのか
-
なぜ
.pyでは動いて.exeでは壊れるのか -
実際に有効だった回避策・解決策
-
採用したバージョン構成
を整理してまとめる。
環境
| 項目 | バージョン |
|---|---|
| OS | Windows 11 |
| Python | 3.11.9 |
| pip | 24.3.1 |
| setuptools | 70.3.0 |
| PyInstaller | 6.18.0 |
| pip-system-certs | 5.3 |
背景
社内ネットワーク(SSL インスペクションあり)環境で、
-
Python アプリを exe 化して配布したい
-
Windows の 証明書ストア(社内CA含む)を使って HTTPS 通信したい
という要件があった。
.py 実行時は問題なかったため、
pip install pip-system-certs
を導入したところ、以下の問題が連鎖的に発生した。
発生した問題
問題① PyInstaller がビルド時に落ちる
SetuptoolsInfo: failed to obtain setuptools info
TypeError: '<' not supported between instances of 'NoneType' and 'tuple'
調査すると、以下が判明。
-
importlib.metadataでは setuptools のバージョンは取得できる -
しかし
import setuptools自体が AssertionError で失敗
AssertionError: ...Python311\Lib\distutils\core.py
→ setuptools の内部ハック(_distutils_hack)が破綻していた
問題② ビルドは通ったが SSL エラーが出る
ビルド時に以下の回避策を入れるとビルド自体は通る:
set SETUPTOOLS_USE_DISTUTILS=stdlib
しかし exe 実行時に、
[SSL: CERTIFICATE_VERIFY_FAILED]
が発生。
-
.py実行では問題なし -
exe だけが失敗
原因の整理
原因① setuptools + distutils の初期化競合
-
pip-system-certsは 起動時に自動介入する仕組みを持つ -
その結果、pip / distutils が setuptools より先に import される
-
setuptools が本来行う
distutils差し替え(_distutils_hack)が失敗 -
import setuptoolsが AssertionError で壊れる -
PyInstaller の
hook-setuptools.pyが setuptools 情報を取れず落ちる
原因② PyInstaller(Frozen 環境)では証明書の自動適用が効かない
-
.py実行:- Windows CA / pip-system-certs の自動設定が有効
-
.exe実行:-
sitecustomize / .pth などの自動処理が効かない
-
requests / urllib3 が certifi(Mozilla CA)だけを見る
-
社内CAを信頼できず SSL 失敗
-
上記はpip-system-certsのPyPIにも記述されているようです。
Client Challenge
解決策
原因①の解決策 ビルドを通す(ビルド時のみ)
set SETUPTOOLS_USE_DISTUTILS=stdlib
pyinstaller your_main.py
-
setuptools の distutils 差し替えを無効化
-
ビルド専用の回避策
-
exe の動作には直接関係しない
※ 警告は出るが問題なし
Reliance on distutils from stdlib is deprecated.
原因②の解決策 exe 側で Windows CA を明示的に使う
pip-system-certs の自動適用に頼らない
1. truststore を使う
# main.py の最上部(requests より前)
import truststore
truststore.inject_into_ssl()
import requests
2. PyInstaller で確実に実行させる(runtime hook)
hook_truststore.py
import truststore
truststore.inject_into_ssl()
ビルド
pyinstaller --onefile --runtime-hook hook_truststore.py your_main.py
これで exe 実行時も Windows の証明書ストア(社内CA含む) が使われる。
まとめ
-
pip-system-certs 導入後の PyInstaller トラブルは
「ビルド環境の破壊」と「exe の SSL 初期化不足」が別問題 -
ビルドが通らないのは setuptools / distutils の初期化競合
-
exe の SSL エラーは Windows CA を見ていないだけ
-
ビルド時と実行時の責務を分離すると解決できる
-
Frozen 環境では「明示的初期化」が最強
同じ問題でハマっている人の助けになれば幸いです。