PythonだけでWebができる「Streamlit」を使ってみたはなし


はじめに

この記事は JSL (日本システム技研) Advent Calendar 2020 - Qiita 20日目の記事です。

毎年恒例、一人アニバーサリー記念です。
この歳になっても迷ってばかりの日々を送っております・・。

普段、開発の仕事をしなくなって久しいので、何を書くか悩みましたが
先日、参加した「みんなのPython勉強会 」 でnikkieさんが紹介していたStreamlitが面白そうなので使ってみた話をします。

Streamlitとは

Streamlit は、Pythonコードでフロントエンド(Web)が書けるライブラリであり、サービスのようです。

今回のゴール

  • Streamlitの公式チュートアルをやりつつ、Connpass API を 使って、直近のイベントデータを表示してみたいと思います。

各種バージョン

  • Python:3.8.0
  • Streamlit:3.9.2
  • Pandas:1.1.5

インストール

$ pip install streamlit

チュートリアルをいじってみる

Hello App

$ streamlit hello

とすると、プロジェクトが作成されます。
ブラウザが起動し、以下のようなデモサイトを構築できます。

streamlitプロジェクトの作成

チュートリアルに従い以下のようにstreamlitや各種ライブラリをimportして

streamlit run [ファイル名]とするとブラウザが起動します。

import streamlit as st

import numpy as np
import pandas as pd

インタラクティブに反映されることを確認する

このような感じにタイトルと、PandasのDataFrameに渡すだけで、インタラクティブにブラウザが更新されます!。

st.title('My first app')

st.write("Here's our first attempt at using data to create a table:")
st.write(pd.DataFrame({
    'first column': [1, 2, 3, 4],
    'second column': [10, 20, 30, 40]
}))

Magic command

write関数以外にもMagic commandsという機能が用意されていて、以下のように変数を書くだけでもwrite関数と同様の挙動になるようです。

df = pd.DataFrame({
  'first column': [1, 2, 3, 4],
  'second column': [110, 200, 300, 400]
})

df

x=10

x

こんな感じでゴリゴリPythonだけで生成されていきます!

Connpass APIからのデータ取得

ざっとチュートリアルをいじってみただけでも色々できそうなので、「Connpass API」から当社が運営する「GEEKLAB.NAGANO」のデータを取得してイベント情報の表示をしてみました。

geeklab_eventlist.py
import streamlit as st

import pandas as pd
import requests, io
from datetime import datetime, date, timedelta
from dateutil.relativedelta import relativedelta
from PIL import Image

st.title('ギークラボイベント開催一覧')

image_url = 'https://connpass-tokyo.s3.amazonaws.com/thumbs/72/9d/729d521ab794e98b4427e9040e8f2fe9.png'
image = Image.open(io.BytesIO(requests.get(image_url).content))
st.image(image, use_column_width=True)

today = datetime.today()
startdate = datetime.strftime(today, '%Y%m')
enddate = "201402"

target_date_set = ['全件'] 
target_date_set.append(startdate)

while startdate > enddate:
  dt = datetime.strptime(startdate, '%Y%m') - relativedelta(months=1)
  startdate = dt.strftime("%Y%m")
  target_date_set.append(startdate)

yyyymm = st.selectbox(
    'イベント開催年月',
    target_date_set
     )

count = st.slider('取得件数', 0, 100, 10)
keyword = st.text_input('キーワード', '')

r = requests.get(f'https://connpass.com/api/v1/event/?series_id=2591&count={count}&ym={yyyymm}&keyword={keyword}')

titles = []
event_date_set = []
participants = []
owners_name = []

for e in r.json()["events"]:
  titles.append(e["title"])

  dt = datetime.fromisoformat(e["started_at"])
  event_date_set.append(datetime.strftime(dt, '%Y/%m/%d'))
  participants.append(e["accepted"])
  owners_name.append(e["owner_display_name"])

df = pd.DataFrame({
  'タイトル': titles,
  '開催日': event_date_set,
  '参加者数': participants,
  '管理者':  owners_name
})
df.style.set_properties(**{'text-align': 'center'})

df

たったこれだけのPythonコードで、ここまで出来るのはスゴイ!!

制限事項

試している中で気づいた制限事項をまとめます。

  • 1ファイル当たり同一のwigetは定義できない
    • 例) selectbox を2つ定義する

デプロイ

https://share.streamlit.io/requirements.txtを含めたGitHubリポジトリを紐付けてあげるとデプロイできます。
週単位で招待メールを通知されるようで、利用できるまで少し時間がかかります。

招待メールが来たら必要事項を入力しているだけで、こんな感じ にデプロイしてくれます。

さいごに

久々の勉強会参加から、Streamlitを触ってみましたが、使ってみて「楽しい」「スゴイ!!」と思えるライブラリに出会えました。若干制限事項はあるものの、データの見えるかを手っ取り早くできる良い仕組みだと思いました。

なによりPythonオンリーで書けるのが良い。

キャッチアップを個人でやり続けるのは、辛いので定期的に勉強会参加することの重要性を再認識した次第です!!。この場をお借りして、nikkieさんに感謝です!!