1. streamlitとは
StreamlitはPythonのウェブアプリケーションを構築するためのフレームワークの一つです。Pythonのコード内に直接書かれたコマンドでウェブアプリケーションを構築するため、HTMLやCSSなどのファイルを扱う必要がありません。さらに、作ったアプリをStreamlit Sharingと呼ばれるサービスを介して、無料でデプロイ・公開できるのが大きな魅力です。
2. 何を作ったか:
以前、kaggleのtarotカードのデータを用いてpythonで作成していた占いゲームを、Streamlit用に焼き直すこととしました。内容は、3枚のカードをランダムに選び、カードとカードの意味する内容を表示するという、単純なものです。
3. 開発過程:
まずはlocalで開発して動作確認まで行いました。streamlitをinstallすると共に、Pythonの仮想環境を作成して有効化します。
pip install streamlit
python -m venv .venv
source .venv/bin/activate
フォルダ内は
- app.py
- requirements.txt
- dataホルダ
- .venvホルダ
ターミナルで以下を起動しlocalhostで動作確認。
(注意)ホスト環境で動いたとしても、デプロイされるのは仮想環境なので、仮想環境下で動作確認することが大切です。
streamlit run app.py
スクリプトを.venvと共にgithubにpushします。
Streamlit Community Cloud アカウントを作成後、Streamlit Sharingにgithubの該当リポジトリを登録して動作を確認します。
しかし、ここでエラーが発生します。ホスト環境では動いたのに。
AttributeError: module 'cv2.dnn' has no attribute 'DictValue'
なかなか解決方法が判らないので、app.py について、cv2でなくPILを使って書き直し、pushし直しました。PILを使ったコードでは問題は起きずデプロイに成功しました。
5. コード:
app.pyのコード内容を示します。st.xxx の部分でWebに表示する内容を設定しています。
import streamlit as st
import pandas as pd
import os
import random
from PIL import Image
data_dir = './cards'
files = os.listdir(data_dir)
data = pd.read_json('./tarot-images.json', orient='records')
data = pd.json_normalize(data['cards'])
data1 = data[['name', 'img', 'fortune_telling']][data['arcana'] == 'Major Arcana']
def predict():
rand3 = random.sample(range(22), k=3)
fortune = []
name = []
file = []
for i in rand3:
fortune.append(data1.loc[i, 'fortune_telling'][0])
name.append(data1.loc[i, 'name'])
file.append(data1.loc[i, 'img'])
times = ['Past', 'Present', 'Future']
images = []
for i in range(3):
img = Image.open(os.path.join(data_dir, file[i]))
images.append(img)
return times, fortune, name, images
st.title("Tarot Reading!")
if st.button("Predict Your Fortune"):
times, fortune, name, images = predict()
col1, col2, col3 = st.columns(3)
with col1:
st.image(images[0], caption=name[0], use_column_width=True)
st.write(f'Your {times[0]} is {name[0]}.')
st.write(f'{fortune[0]}.')
with col2:
st.image(images[1], caption=name[1], use_column_width=True)
st.write(f'Your {times[1]} is {name[1]}.')
st.write(f'{fortune[1]}.')
with col3:
st.image(images[2], caption=name[2], use_column_width=True)
st.write(f'Your {times[2]} is {name[2]}.')
st.write(f'{fortune[2]}.')
6. アプリへのリンク:
7. 今後の展望:
streamlitのおかげで、pythonコードのWebアプリ化のハードルが一気に下がったように思います。機械学習でトレーニング済みのモデルを使ったアプリなども作れそうな気がします。
8. 参考文献やリソース:
https://streamlit.io/
https://docs.streamlit.io/
https://share.streamlit.io/