14
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Streamlit を超手軽に配布したい ― embedded Python でサーバー不要の配布パッケージを作る

Last updated at Posted at 2025-12-14

はじめに

はじめまして、@umd55 です。

15年くらいメイクアップ化粧料の研究開発・処方設計をしていましたが、縁あって本年より社内ツール開発をしています。

初めてのプログラミング言語は Python で、爆速で開発したかったので Streamlit で開発することが多くなりました。

「Streamlit でいい感じのプロトタイプができた!チームメンバーに使ってもらいたい。」

次第にそう思うようになりました。しかしながら、サーバー構築やデプロイはハードルが高く、プロトタイプは爆速でも、共有するのに失速してしまう。

「作る」より「配る」が難しい・・・これが意外な壁でした。

そこでこの記事では、embedded Python + bat ファイルを使って、Python 未インストールの PC でも動く Streamlit アプリを配布する方法を紹介します。

共有ファイルサーバー上の CSV を読み込んで表示する、簡易検索アプリを例に解説します。


この方法のメリット

  • サーバー不要: 今すぐ配布できる
  • Python 未インストールでも動く: 配布先の PC に Python がなくても OK
  • bat ダブルクリックで起動: デスクトップアプリ風の体験

全体像

開発者がやること

  1. uv をインストール
  2. uv で Streamlit アプリを開発
  3. requirements.txt を作成
  4. embedded Python を準備し、ライブラリをインストール
  5. フォルダを整えて zip 化
  6. チームに配布

配布先ユーザーがやること

  1. zip を展開
  2. bat をダブルクリック

これだけです。
めちゃくちゃ手軽です。

最終的な配布物

MyApp/
├── bin/
│   ├── python/           # embedded Python(pip install 済み)
│   │   ├── python.exe
│   │   ├── python313._pth
│   │   ├── Lib/
│   │   ├── Scripts/
│   │   └── ...
│   └── main.py           # Streamlit アプリ
└── MyApp.bat             # 起動用

ユーザーから見ると フォルダ1つ + bat 1つ だけです。シンプルなのでユーザーも迷いません。


前提条件

  • OS: Windows 10 / 11
  • 開発者: uv をこれからインストール(Python 不要)
  • 配布先: Python 未インストールでも OK

Part 1: 開発者向け手順

Step 1: uv のインストール

PowerShell を開いて以下を実行します。

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

インストール後、ターミナルを再起動して確認します。

uv --version

バージョンが表示されれば OK です。

💡 uv とは?

uv は Rust 製の高速な Python パッケージマネージャーです。pip より 10〜100 倍高速で、仮想環境の作成・管理も一括で行えます。Python 自体のインストールも uv が自動で行ってくれるため、開発マシンに Python がなくても大丈夫です。


Step 2: Streamlit アプリの作成

作業フォルダを作成し、uv でプロジェクトを初期化します。

mkdir streamlit-app
cd streamlit-app
uv init

uv init を実行すると、以下のファイルが自動生成されます。

streamlit-app/
├── .git/
├── .gitignore
├── .python-version
├── main.py            # ← この中身を Streamlit アプリに書き換えます
├── pyproject.toml
└── README.md

main.py には Hello World のテンプレートが入っています。これを Streamlit アプリに書き換えていきます。

Streamlit を追加します。

uv add streamlit pandas

main.py を以下の内容に書き換えます。共有ファイルサーバーの CSV を読み込んで表示する簡易検索アプリの例です。ここでは犬種データを例に解説します。

import streamlit as st
import pandas as pd
from pathlib import Path

# ===========================================
# 設定(ここを環境に合わせて変更)
# ===========================================
# UNC パス例: \\\\server\\share\\data
DATA_DIR = Path(r"\\server\share\data")
CSV_FILE = DATA_DIR / "dogs.csv"

# ===========================================
# アプリ本体
# ===========================================
st.set_page_config(page_title="犬種図鑑", layout="wide")
st.title("犬種図鑑")


@st.cache_data
def load_data():
    if not CSV_FILE.exists():
        st.error(f"CSV ファイルが見つかりません: {CSV_FILE}")
        return pd.DataFrame()
    return pd.read_csv(CSV_FILE, encoding="utf-8")


df = load_data()

if df.empty:
    st.warning("データがありません。CSV ファイルのパスを確認してください。")
    st.stop()

# サイドバー:検索フィルター
st.sidebar.header("検索条件")
search_text = st.sidebar.text_input("犬種名で検索")

# グループフィルター
groups = ["すべて"] + sorted(df["group"].dropna().unique().tolist())
selected_group = st.sidebar.selectbox("グループ", groups)

# サイズフィルター
sizes = ["すべて"] + df["size"].dropna().unique().tolist()
selected_size = st.sidebar.selectbox("サイズ", sizes)

# フィルタリング
filtered_df = df.copy()

if search_text:
    filtered_df = filtered_df[
        filtered_df["name"].str.contains(search_text, case=False, na=False)
        | filtered_df["name_en"].str.contains(search_text, case=False, na=False)
    ]

if selected_group != "すべて":
    filtered_df = filtered_df[filtered_df["group"] == selected_group]

if selected_size != "すべて":
    filtered_df = filtered_df[filtered_df["size"] == selected_size]

# 結果表示
st.subheader(f"検索結果: {len(filtered_df)}")

# 表示するカラムを選択
display_columns = ["name", "name_en", "group", "size", "origin", "weight_kg", "height_cm", "lifespan"]
display_df = filtered_df[display_columns].copy()

st.dataframe(
    display_df,
    column_config={
        "name": st.column_config.TextColumn("犬種名", width="medium"),
        "name_en": st.column_config.TextColumn("英語名", width="medium"),
        "group": st.column_config.TextColumn("グループ", width="small"),
        "size": st.column_config.TextColumn("サイズ", width="small"),
        "origin": st.column_config.TextColumn("原産国", width="small"),
        "weight_kg": st.column_config.NumberColumn("体重(kg)", width="small"),
        "height_cm": st.column_config.NumberColumn("体高(cm)", width="small"),
        "lifespan": st.column_config.NumberColumn("寿命(年)", width="small"),
    },
    hide_index=True,
    width="stretch",
)

動作確認します。

uv run streamlit run main.py

ブラウザが開き、アプリが表示されれば OK です。Ctrl + C で停止します。

streamlit_demoapp.png

サンプル CSV(dogs.csv)
id,name,name_en,group,size,origin,weight_kg,height_cm,lifespan
1,柴犬,Shiba Inu,日本犬,中型,日本,9,38,13
2,秋田犬,Akita,日本犬,大型,日本,45,66,11
3,トイプードル,Toy Poodle,愛玩犬,小型,フランス,3,26,14
4,チワワ,Chihuahua,愛玩犬,小型,メキシコ,2,18,15
5,ゴールデンレトリバー,Golden Retriever,レトリバー,大型,イギリス,32,58,11

Step 3: requirements.txt の作成

embedded Python にインストールするためのライブラリ一覧を出力します。

uv export --format requirements-txt --no-hashes > requirements.txt

💡 --no-hashes オプションについて

uv export はデフォルトでハッシュ付きの requirements.txt を出力しますが、embedded Python の pip ではハッシュ検証がうまくいかないことがあります。--no-hashes を付けることでシンプルな形式になります。


Step 4: 配布用フォルダの作成と embedded Python の準備

開発環境(streamlit-app/)と配布物は分離します。

開発環境には uv で作成した .venv/pyproject.tomluv.lock などがありますが、これらは配布物には不要なためです。

配布用フォルダを作成

streamlit-app/親ディレクトリに移動してから、MyApp フォルダを作成します。

cd ..
mkdir MyApp
mkdir MyApp/bin

embedded Python のダウンロード

Python 公式サイト から Windows embeddable package (64-bit) をダウンロードします。

この記事執筆時点の最新版は Python 3.13.10 です。

直接リンク: https://www.python.org/ftp/python/3.13.10/python-3.13.10-embed-amd64.zip

展開・配置

  1. ダウンロードした zip を展開
  2. 展開したフォルダを python にリネーム
  3. MyApp/bin/ の中に python フォルダを配置
MyApp/
└── bin/
    └── python/          # ← ここに展開した中身を配置
        ├── python.exe
        ├── python313._pth
        ├── python313.zip
        └── ...

pip を使えるようにする

embedded Python はそのままでは pip が使えません。以下の手順で有効化します。

1. python313._pth を編集

MyApp/bin/python/python313._pth をテキストエディタで開き、#import site のコメントを外します。

python313.zip
.

# Uncomment to run site.main() automatically
- #import site
+ import site

2. get-pip.py をダウンロードして実行

MyApp フォルダに移動してから実行します。

cd MyApp

# get-pip.py をダウンロード
Invoke-WebRequest -Uri https://bootstrap.pypa.io/get-pip.py -OutFile get-pip.py

# embedded Python で実行
.\bin\python\python.exe get-pip.py

# 不要になったら削除
Remove-Item get-pip.py

💡 なぜこれらの設定が必要か?

._pth ファイルについて:
embedded Python は「埋め込み用途」を想定しており、デフォルトでは site-packages を読み込まない設定になっています。import site を有効にすることで、pip でインストールしたパッケージが正しく読み込まれるようになります。._pth ファイルは Python のパス設定ファイルで、ここに記載されたパスのみが sys.path に追加されます。

get-pip.py について:
embedded Python には pip が同梱されていません。get-pip.py は Python 公式が提供する pip インストール用のブートストラップスクリプトです。このスクリプトを実行することで、pip 本体とその依存パッケージ(setuptools、wheel)がインストールされます。


Step 5: ライブラリのインストール

MyApp フォルダ内で、embedded Python の pip を使って、requirements.txt のライブラリをインストールします。

.\bin\python\python.exe -m pip install -r ..\streamlit-app\requirements.txt

インストールが完了したら確認します。

.\bin\python\python.exe -m pip list

streamlit、pandas などがインストールされていれば OK です。


Step 6: アプリの配置と bat ファイルの作成

main.py をコピー

開発環境から main.pyMyApp/bin/ にコピーします。

Copy-Item ..\streamlit-app\main.py bin\

bat ファイルを作成

MyApp フォルダ内に MyApp.bat を作成します。

@echo off
cd /d %~dp0
bin\python\python.exe -m streamlit run bin\main.py
pause

💡 bat ファイルの解説

bat ファイルとは?
bat(バッチ)ファイルは、Windows のコマンドを記述したテキストファイルです。拡張子を .bat にすると、ダブルクリックで中に書かれたコマンドが順番に実行されます。プログラムの起動手順を自動化したいときによく使われます。今回は「Python を起動して Streamlit アプリを実行する」という手順を bat ファイルにまとめています。

各行の意味:

  • @echo off :コマンドの表示を抑制
  • cd /d %~dp0 :は bat ファイルのあるディレクトリに移動(ドライブをまたいでも動作)
  • pause :エラー時にウィンドウがすぐ閉じないように

動作確認

MyApp.bat をダブルクリックして、アプリが起動することを確認します。

フォルダ構成の最終形

MyApp/
├── bin/
│   ├── python/
│   │   ├── python.exe
│   │   ├── python313._pth
│   │   ├── Lib/
│   │   ├── Scripts/
│   │   └── ...
│   └── main.py
└── MyApp.bat

zip 化

親ディレクトリに戻ってから、フォルダごと zip に圧縮して配布します。

cd ..
Compress-Archive -Path MyApp -DestinationPath MyApp.zip

Part 2: 配布先ユーザー向け手順

使い方(これだけ!)

  1. 受け取った MyApp.zip を展開
  2. MyApp.bat をダブルクリック
  3. コマンドプロンプトが開き、しばらく待つとブラウザが自動で開く
  4. アプリが表示される

Python のインストールは不要です。

終了方法

コマンドプロンプトで Ctrl + C を押すか、ウィンドウを閉じます。

初回起動時のファイアウォール警告

初回起動時に「Windows セキュリティの重要な警告」ダイアログが表示されることがあります。

これは Streamlit が Web サーバーとして動作するため、Windows ファイアウォールがネットワークアクセスを許可するか確認しています。

選択 動作
キャンセル 自分の PC(localhost)からのみアクセス可能
許可 同じネットワーク内の他の PC からもアクセス可能

1人で使う場合は「キャンセル」で問題ありません。 localhost へのアクセスはファイアウォールに関係なく動作します。


これで配布パッケージの完成です!

bat ファイルをダブルクリックするだけで Streamlit アプリが起動する、超手軽な配布パッケージができました。

以降は、より便利に使うための Tips を紹介します。ご参考まで。


Tips

ショートカットでもっと便利に

bat ファイルのショートカットを作成すると、デスクトップやタスクバーに配置できて便利です。

  1. MyApp.bat を右クリック → 「ショートカットの作成」
  2. ショートカットをデスクトップなど好きな場所に移動
  3. 好みでアイコンも変更可能(右クリック → プロパティ → アイコンの変更)

よくあるエラーと対処

エラー 原因 対処
python が見つからない bat 内のパスが間違っている bin\python\python.exe のパスを確認
ModuleNotFoundError: No module named 'xxx' ライブラリ未インストール pip install を再実行
ブラウザが開かない ファイアウォール or ポートブロック http://localhost:8501 を手動で開く
CSV の文字化け エンコーディングの不一致 encoding='cp932' or 'utf-8' を指定
python313._pth の編集を忘れた pip は通るが import で失敗 import site のコメントを外す

この方法の限界と次のステップ

この方法ではソースコードが見える状態で配布することになります。あくまで社内共有・プロトタイピング用途としてご利用ください。

この方法が向いているケース

  • ✅ プロトタイプの共有
  • ✅ 少人数(数名〜十数名)での利用
  • ✅ 社内ネットワーク内での利用

この方法が向いていないケース

  • ❌ 多人数での同時アクセス(数十人以上)
  • ❌ 社外への配布
  • ❌ 本番運用・長期運用

おわりに

この記事では、embedded Python + bat ファイル を使って、Streamlit アプリをサーバー不要で配布する方法を紹介しました。

開発者側は、uv で快適に開発しながら、配布用には embedded Python を使うことで環境構築の手間を省けます。ユーザー側は、zip を展開して bat をダブルクリックするだけ。Python のインストールも不要で、すぐにアプリを使い始められます。

プロトタイプ共有に最適な方法ですが、本格運用には別の方法を検討してくださいね。

「サーバー立てるほどじゃないけど、チームメンバーに使ってもらいたい!」そんなときに、ぜひ試してみてください!


ちなみに、Streamlit を手軽に共有する方法はこれだけではありません。明日のアドベントカレンダーでは、また違ったアプローチが紹介される予定です。そちらもぜひお楽しみに!


参考リンク

14
2
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
14
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?