【Webアプリ起動】Webアプリを空きポートで自動起動するWindowsバッチ

備忘録

― .venv を強制使用し、8501〜8600の空きポートを自動探索する実用ランチャー ―

Streamlitを開発していると、よく次の問題が起きます。

  • すでに 8501ポートが使用中
  • Pythonの 仮想環境が違う
  • 起動コマンドを毎回打つのが面倒

例えば次のようなエラーです。

Port 8501 is already in use

こういうときに便利なのが
Streamlit起動専用のランチャーバッチです。

今回紹介するバッチは次のことを自動で行います。

.venv の Python を使用
✔ 空きポートを自動探索
✔ Streamlitを起動


全体アーキテクチャ

まず、このスクリプトの構造を図で見てみます。

+----------------------+
| run_streamlit.bat |
+----------+-----------+
|
v
仮想環境チェック
(.venv/Scripts/python.exe) |
v
ポート探索ループ
8501 → 8502 → 8503 ... |
v
空きポート発見 |
v
Streamlit起動
python -m streamlit run app.py

つまり

仮想環境確認

ポート探索

Streamlit起動

という3段階構造です。


想定ディレクトリ構成

このスクリプトは次の構成を前提にしています。

my_streamlit_project

├─ app.py
├─ run_app.bat

└─ .venv
└─ Scripts
└─ python.exe

ポイントは

.bat と app.py が同じフォルダ

です。


バッチファイル全体

@echo off
setlocal:: ===== 初期設定(パス・ポート範囲)=================================
set "ROOT_DIR=%~dp0"
set "PYTHON_EXE=%ROOT_DIR%.venv\Scripts\python.exe"
set /a "PORT=8501"
set /a "MAX_PORT=8600":: ===== 前提チェック(.venv の存在確認)==============================
if not exist "%PYTHON_EXE%" (
echo [ERROR] Python virtual environment not found: "%PYTHON_EXE%"
echo Please create it first: python -m venv .venv
exit /b 1
):: ===== 空きポート探索ループ =========================================
:find_port
netstat -ano | findstr /R /C:":%PORT% " >nul  ☞付録①で解説
if %errorlevel%==0 (              ☞付録②で解説
set /a "PORT+=1"
if %PORT% GTR %MAX_PORT% (
echo [ERROR] No available port found between 8501 and %MAX_PORT%.
exit /b 1
)
goto :find_port
):: ===== アプリ起動 ================================================
echo [INFO] Starting Streamlit on port %PORT%...
"%PYTHON_EXE%" -m streamlit run "%ROOT_DIR%app.py" --server.port %PORT%

Step1 仮想環境Pythonの強制使用

通常の起動はこうです。

streamlit run app.py

しかしこれだと

どのPythonが使われるか不明

になります。

例えば

Python3.11
Python3.12
Anaconda
venv

が混ざると環境事故が起きます。

そこでこのコードです。

set "PYTHON_EXE=%ROOT_DIR%.venv\Scripts\python.exe"

つまり

プロジェクト/.venv/Scripts/python.exe

強制使用します。

図にすると

通常起動streamlit run app.py

どのPython?(不明)このバッチ.venv/python.exe

確実に仮想環境

これはかなり重要な設計です。


Step2 仮想環境存在チェック

次に .venv の存在を確認します。

if not exist "%PYTHON_EXE%" (
echo error
exit
)

図で見ると

      start
|
v
.venv/python.exe exists ?
|
+----+----+
| |
yes no
| |
run error

もし .venv が無い場合

[ERROR] Python virtual environment not found

と表示されます。


Step3 空きポート探索

ここがこのスクリプトのコアです。

netstat -ano | findstr ":8501"

これは

現在使用されているポート一覧

を調べています。


ポート探索の流れ

図で見るとこうです。

PORT = 8501      |
v8501 使用中?
|
+----+----+
| |
yes no
| |
8502 起動
|
v8502 使用中?

つまり

8501
8502
8503
...

を順番に調べます。


Step4 Streamlit起動

最後にStreamlitを起動します。

python -m streamlit run app.py

ただしPythonは

.venv/python.exe

です。

つまり実際のコマンドは

.venv/Scripts/python.exe

streamlit module

run app.py

です。


実行例

例えば

8501 使用中
8502 使用中
8503 空き

だった場合

[INFO] Starting Streamlit on port 8503

となります。

アクセスURLは

http://localhost:8503

です。


この設計のメリット

1 Python環境事故を防ぐ

pip install
Python version mismatch

などを防ぎます。


2 ポート競合を防ぐ

Streamlitは

8501固定

なので競合が起きやすいです。

このバッチなら

8501 → 8600

まで自動探索します。


3 ダブルクリック起動できる

開発者以外でも

run_app.bat

をクリックするだけです。


改良案

さらに実務レベルにするなら次がおすすめです。

改良1 URL表示

echo http://localhost:%PORT%

改良2 ブラウザ自動起動

start http://localhost:%PORT%

改良3 requirements自動チェック

pip install -r requirements.txt

まとめ

このバッチは

Streamlit開発の小さなDevOpsツール

です。

機能は3つ。

1 仮想環境確認
2 空きポート探索
3 Streamlit起動

図でまとめると

run_app.bat
|
v
仮想環境確認
|
v
ポート探索
|
v
Streamlit起動

開発現場ではこういう小さい自動化ツールが効きます。

付録

付録①:Port検索: netstat -ano | findstr /R /C:":%PORT% " >nul

netstat -ano | findstr /R /C:":%PORT% " >nul

”ポートの使用状況を検索する”

この行は、大きく3つのパーツに分かれています。

① netstat -ano

ネットワークの接続状態を表示するコマンドです。

  • -a: すべての接続と待機ポートを表示します。
  • -n: アドレスとポート番号を(名前ではなく)数値で表示します。
  • -o: そのポートを使っているプロセスのID(PID)も表示します。

② | findstr /R /C:":%PORT% "

パイプ(|)を使って、netstatの結果から特定の文字列を探します。

  • /R: 検索文字列を正規表現として扱います。
  • /C:":%PORT% ": 指定した文字列(:%PORT% )を検索します。
    • ここがポイント!%PORT% の前後に : と (半角スペース)を入れることで、例えばポート 80 を探している時に 8080180 といった他のポートが誤ってヒットするのを防いでいます。

③ >nul

検索結果(見つかった行のテキスト)を画面に表示せず、ゴミ箱に捨てます。今回は「見つかったかどうか(終了コード)」だけが重要なので、表示は不要というわけです。


付録②:判定と条件分岐:if %errorlevel%==0

if %errorlevel%==0 (

ここで、1行目の実行結果を受けて「もし〜なら」という処理を行います。

  • %errorlevel%: 直前に実行したコマンドの「終了ステータス」が格納される変数です。
    • 0: findstr が指定した文字列を見つけた(=ポートが使用中)。
    • 1 以上: 見つからなかった(=ポートは空いている)。
  • if %errorlevel%==0 (: つまり、**「ポートが使用中だった場合、ここから先の処理( ( 以降)を実行せよ」**という意味になります。

コメント

タイトルとURLをコピーしました