サイトアイコン アマチュア無線局JS2IIU

【Streamlit】キャッシングでアプリのパフォーマンスを向上させる:@st.cache_data, @st.cache_resource

こんにちは、JS2IIUです。
今回はStreamlitのキャッシュ機能についてみていきます。処理速度を改善して、ユーザーにとって快適なサービスを提供できるようになります。今回もよろしくお願いします。

はじめに

Streamlitでアプリを作っていて、以下のような経験はありませんか?

こうした問題を解決して、アプリをサクサク動かす方法が「キャッシング」です。
この記事では、Streamlitでよく使われるキャッシュ機能 @st.cache_data@st.cache_resource の使い方を、初心者の方でも理解しやすいように、具体例を使って丁寧に解説します。

キャッシュとは?

キャッシュの基本概念

キャッシュとは、一度行った処理の結果を保存しておき、次に同じ処理が必要になったときに、再実行せずに保存済みの結果を再利用する仕組みです。

例えば、大きなCSVファイルを読み込むのに毎回10秒かかるとしたら、キャッシュを使えば初回だけ読み込み、次回からは即座に結果を再利用できます。

Streamlitには、このキャッシュ機能を簡単に使える2つのデコレーターが用意されています:

@st.cache_data の使い方

使いどころ

基本構文

Python
@st.cache_data
def 関数名():
    # 時間のかかる処理
    return 結果

実践例:CSVファイルの読み込み

Python
import streamlit as st
import pandas as pd

@st.cache_data
def load_data():
    st.write("📦 データを読み込んでいます...")
    df = pd.read_csv("https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv")
    return df

st.title("Irisデータセットの表示")
df = load_data()
st.dataframe(df)

解説

このコードでは、初回のみCSVファイルが読み込まれ、”📦 データを読み込んでいます…” が表示されます。
2回目以降の実行では、キャッシュからデータが取得され、読み込み処理がスキップされます。

@st.cache_resource の使い方

使いどころ

実践例:重たい処理のキャッシュ

Python
import streamlit as st
import time

@st.cache_resource
def load_model():
    st.write("🤖 モデルを読み込んでいます...")
    time.sleep(5)  # 擬似的に時間のかかる処理
    return "モデル"  # 実際はモデルオブジェクトを返す

st.title("モデルのキャッシュデモ")
model = load_model()
st.success(f"取得したリソース: {model}")

解説

このコードでは、初回実行時に5秒の遅延がありますが、2回目以降はキャッシュが使われ即座に表示されます。

よくあるエラーと対処法

1. キャッシュ対象の関数でStreamlitのAPIを呼んでしまう

エラー内容: st.write などのUI操作をキャッシュ関数の中で使うと警告が出ることがあります。

対処法: 処理部分とUI部分を分ける。

NG例:

Python
@st.cache_data
def load():
    st.write("読み込み中...")  # UI操作 → NG
    return 100

OK例:

Python
@st.cache_data
def load():
    return 100

st.write("読み込み中...")
data = load()

2. キャッシュが効かない(毎回処理が走る)

原因: 関数の引数が毎回異なる場合、キャッシュは再利用されません。

例:

Python
@st.cache_data
def compute(x):
    return x ** 2

value = compute(time.time())  # 毎回異なる値 → キャッシュされない

対処法: 引数が毎回同じになるように工夫する。

処理時間の比較で効果を確認

Python
import streamlit as st
import time

@st.cache_data
def slow_function():
    time.sleep(3)
    return "完了"

st.title("キャッシュ効果の確認")
start = time.time()
result = slow_function()
elapsed = time.time() - start

st.write(f"結果: {result}")
st.write(f"処理時間: {elapsed:.2f}秒")
https://js2iiu.com/wp-content/uploads/2025/05/67_02.mov

実行結果

まとめ

参考リンク

最後まで読んでいただきありがとうございました。

モバイルバージョンを終了