PyInstaller exe 納品前チェックリスト ― 2つの実事故が教えた7つの改札
投稿日:2026.08.20
CATEGORY
- 製造業DX
「ビルドが通ったから大丈夫」と判断してexeを現場に出荷したことが、私たちには2回あります。1回は実行時にしか判明しない依存漏れが原因でした。もう1回は、前任担当者から受け継いだソースコードが現場で稼働していたexeより新しい世代だったことに気づかないまま再ビルドし、本番未反映の変更が現場で初めて動き出した結果でした。この2つの事故と、同時期に複数プロダクトを横断して点検した際に見つかった実在の穴を踏まえ、私たちはexeを納品する全プロダクトで、出荷前に必ず通す7つの改札を義務化しています。
ビルドが通った先で起きた2つの事故
1つ目の事故は、QRコード生成ライブラリが依存ライブラリを関数内で遅延importしていたために、ビルド環境にその依存が無くてもビルドが成功し、現場でQRコード生成が全数失敗した事例です。この経緯と対策は姉妹記事(PyInstaller のビルド成功は動作保証ではない)で詳しく書いています。
2つ目の事故は、別の保守案件で起きました。前任担当者から受領したソースコードの最終コミットが、現場で稼働していたexeのビルドより新しい世代だったのです。世代のズレに気づかないまま検証・再ビルドして納品したところ、前任コミットに含まれていた本番未反映の変更が、再ビルドをきっかけに初めて現場で動き出しました。想定外の挙動が発生し、顧客からロールバック(旧バージョンへの切り戻し)を求められました。**受領したソースコードは、現場で稼働しているバイナリと同じとは限りません。**この前提を欠いたまま再ビルドすることが、2つ目の事故の根本原因でした。
出荷前に通す4つの改札 ― どのビルドにも共通
どのプロダクトをビルドする時も、私たちは次の4つの改札を出荷前に通しています。このうち改札1〜3は、2つの事故そのものからではなく、同時期に複数プロダクトを横断して点検した際に見つかった実例がもとになっています。受領・引き継ぎ品には、これに加えてさらに3つの改札が追加されます。

改札1: ビルド元commitを記録する。ビルド直後にcommit hashをファイルへ出力し、納品zipに同梱します。これを怠ると、現場でどのコードが動いているexeなのかを後から特定できなくなります。実際に、distのexeがHEADより古いのに、納品zip複数本とcommitの対応表が無く、現場のコードを特定できない状態を招いたことがあります。
改札2: ビルドブランチを確認する。main・developなど正規のブランチ以外、たとえばデバッグ用のログを毎周期大量に吐くWIPブランチからビルドしていないかを確認します。
改札3: ビルド環境を固定する。ビルドスクリプトにvenvのactivateとPython版を明記し、ビルド後はgrep -ao "python3..dll" <exe>でexeに埋め込まれたPython版が意図通りか照合します。加えて、ビルド前に必要な依存を実際にimportしてみて、失敗したらビルド自体を止めるゲートも組み込んでいます。ただしこのゲートで防げるのはビルド環境側の依存欠落だけです。関数内で遅延importされる依存はこのゲートをすり抜けます(その対策は姉妹記事の--hidden-importと--cleanの恒久付与が担います)。
改札4: ビルド時スモークのログを読む。必ず本番相当の設定ファイルをexeと同じフォルダに置いて起動する。設定ファイル無しのスモークは設定読込エラーで本来の処理に到達せず、欠陥を素通りさせます。1つ目の事故は、まさにこの見落としを経て出荷されました。確認しているのは3点です。起動後のログに想定外のERRORが出ていないこと、機能生成物のタイムスタンプが起動時刻に更新されていること、ログの増加速度が異常でないことです。
受領・引き継ぎ品に追加される3つの改札
ところが、前任担当者から受領したソースや、他社から引き継いだプロダクトには、上の4つだけでは止められない危険が別に潜んでいます。初めて再ビルドする時は、さらに3つの改札を通します。2つ目の事故が教えた、受領品特有の危険への対策です。
改札5: 受領・引き継ぎ品の初回再ビルドは世代突合を行う。稼働exeのビルド日時と、受領したソースの最終コミット日時を突き合わせます。稼働exeより新しいコミットがあれば、そのdiffを読み「再ビルドで初めて有効になる挙動」を洗い出し、客先に確認してから納品します。2つ目の事故は、この突合を省いたまま進めたことが根本原因でした。
改札6: 受領時に現場の実稼働ログを保全する。受領直後に、現場で実際に動いているexeのログを2〜3日分保全しておきます。後日の障害調査で「以前からこうだったのか、再ビルドで変わったのか」を判定する最も直接的な材料は、このログです。保全していたプロダクトでは、これが原因特定を直接助けました。
改札7: 受領zip同梱の旧exeは受領直後に隔離リネームする。私たちがビルドしたexeと同じフォルダに、先方が過去にビルドしたexeを同名のまま置いておくと、どちらを検証しているのか取り違える事故を誘発します。実際に、先方ビルドのexeが私たちのdistフォルダに居座っていたことがありました。受領した時点で、旧exeはフォルダ名や拡張子を変えて隔離しておきます。

まとめ
あなたが今日から確認できるのは、直近で受領・引き継いだプロダクトの稼働exeより、ソースの最終コミットが新しくなっていないかどうかです(改札5)。差分があれば、それは「まだ現場で一度も動いていない変更」であり、次の再ビルドで初めて姿を現します。
7つの改札は、1人の注意力に頼らず出荷前の見落としを減らすための仕組みです。毎回のビルドだけで完結するプロダクトなら4つで足りますが、受領・引き継ぎ品はソースとバイナリの世代が食い違っている可能性を常に抱えているため、残り3つが必要になります。中でも、受領直後の隔離リネーム(改札7)は再ビルドすら要らず、フォルダを開くだけで今日から始められます。
出典:
- 私たちがexe納品プロダクトで運用している出荷前チェックリスト(社内一次情報)
- 姉妹記事: PyInstaller のビルド成功は動作保証ではない
※ この記事は AI を使用しています。Leadeas が自社開発した AI エージェント基盤で下書きを作成し、人間のレビューを経て公開しています。AI ネイティブ開発会社として自社の技術をそのまま実演する目的で、この手法を用いています。(詳しくは AI 利用ポリシー)

