【Streamlit】初體驗


初體驗

官網很好看:傳送門

快速安裝:conda install -c conda-forge streamlit

后續可以在此環境下直接輸入一個:streamlit hello便會自動跳轉一個本地網頁:http://localhost:8501/,有些像Jupyter:

然后自動跳轉瀏覽器,有幾個自帶的Demo可以感受一下:

關閉進程只需要在終端輸入Ctrl+C即可。

可以把官網Demo復制到本地,在文件夾路徑下開啟終端,通過輸入streamlit run test1.py運行:

import streamlit as st
import time
import numpy as np

st.title('My first app~')
chart_data = pd.DataFrame(
     np.random.randn(20, 3),
     columns=['a', 'b', 'c'])

st.line_chart(chart_data)

st.button("Re-run")

如果有報錯:AttributeError: module 'google.protobuf.descriptor' has no attribute '_internal_create_key'
進行:pip install --upgrade protobuf


入門操作

參考這個 Getting started.

跟着上面入門教程添加內容。頁面上會根據每添加一個內容項在下面疊加一個模塊。

當然,直接往下無腦疊加代碼在下拉選框部分報錯了!!!需要注意的是下面兩個似乎不可同時使用:

# 疊加形式的下拉選框
# option = st.selectbox(
#     'Which number do you like best?',
#      df['first column'])

# 'You selected: ', option

# 將下拉選框移動至左側
option = st.sidebar.selectbox(
    'Which number do you like best?',
     df['first column'])

'You selected:', option

跟到現在的呈現形式:

這里Doc里面有句Most of the elements you can put into your app can also be put into a sidebar using this syntax: st.sidebar.[element_name](),說的是任何加入app(即是頁面主體部分的內容)都可放入sidebar部分,只是將調用的模塊前面添加.sidebar即可。


水平布局:使用st.beta_columns(N)設置app的同行左右依次相依,將這一行切分為N列:

left_column, right_column = st.beta_columns(2)
pressed = left_column.button('Press me?')  # 左側放置button按鍵
if pressed:
    right_column.write("Woohoo!")  # 若是按鍵點擊,右側出現文字

可折疊文本beta_expander()模塊

expander = st.beta_expander("FAQ")
expander.write("Here you could put in some really, really long explanations...")

得到:


時間進度條st.progress()模塊

# 添加一個占位 placeholder
latest_iteration = st.empty()
bar = st.progress(0)

for i in range(100):
  # Update the progress bar with each iteration.
  latest_iteration.text(f'Iteration {i+1}')
  bar.progress(i + 1)
  time.sleep(0.1)

至此,官網入門部分指引完畢。

基本功能

進入CookBook部分。

import streamlit as st
import pandas as pd
import numpy as np


st.title('My Second App~')

DATE_COLUMN = 'date/time'
DATA_URL = ('https://s3-us-west-2.amazonaws.com/streamlit-demo-data/uber-raw-data-sep14.csv.gz')

# Streamlit默認每次改動都會重新加載文件,加上此cache裝飾器后可以讓其在第一次時緩存,后續加載與本地緩存對比檢測是否有變動
# cache是會進行代碼遍歷,檢測套上該裝飾器的函數的參數&函數體&嵌套子函數的所有與此函數相關的變化
# cache是累計式緩存,比如給某參數x用slider指定返回,每執行一次都會被記錄一次值!
@st.cache  
def load_data(nrows):
    data = pd.read_csv(DATA_URL, nrows=nrows)
    lowercase = lambda x: str(x).lower()
    data.rename(lowercase, axis='columns', inplace=True)
    data[DATE_COLUMN] = pd.to_datetime(data[DATE_COLUMN])
    return data


data_load_state = st.text('Loading data...')
data = load_data(10000)
# data_load_state.text('Loading data...done!')  # 只需要申明一次
data_load_state.text("Done! (using st.cache)")

# 是否展示數據
if st.checkbox('Show raw data'):
    st.subheader('Raw data')
    st.write(data)

hist_values = np.histogram(data[DATE_COLUMN].dt.hour, bins=24, range=(0,24))[0]  # 將時間按照2小時繪制頻率圖
st.subheader('Time hisChart')
st.bar_chart(hist_values)

# Slider組件
hour_to_filter = st.sidebar.slider('hour', 0, 23, 17)  # 此時並未關聯某個模塊
st.subheader('Map with Slider')
st.map(data[data[DATE_COLUMN].dt.hour == hour_to_filter])

得到:

Ps: map方法需要有字段列名為lon、lat或全稱形式。


后續幾個篇章值得注意的是:這個模塊可以和前端語法Html+JS等自定義組件搭配使用(網不好 看不到...)。

至此,tutorial部分完結。


再談cache

import streamlit as st
import time

@st.cache(suppress_st_warning=True)
def expensive_computation(a, b):
    st.write("Cache miss: expensive_computation(", a, ",", b, ") ran")
    time.sleep(2)  # This makes the function take 2s to run
    return {"output": a * b}  # 👈 Mutable object

a = 2
b = 21
res = expensive_computation(a, b)

st.write("Result:", res)

res["output"] = "result was manually mutated"  # 👈 Mutated cached value

st.write("Mutated result:", res)

這個部分首次運行沒啥問題,一眼看出結果,如果rerun一次便會報錯,因為Streamlit的緩存機制限制,Doc里有個caching_issues話題,推薦使用import copy方法deepcopy一個出來。

然后若是清理緩存,終端下輸入:streamlit cache clear即可。

Session屬性
由於每次交互操作都會導致StreamLit都會重運行,那如何維持會話狀態呢?比如我想嘗試一下每次點擊累加,但rerun就會讓程序每次都是在初始值的基礎上變化。。。

這個用起來還有生疏,而且暫時沒具體應用場景。先不做進一步記錄。

import streamlit as st

st.title('Counter Example using Callbacks')
if 'count' not in st.session_state:
	st.session_state.count = 0  # 或st.session_state['count']

def increment_counter():
	st.session_state.count += 1

st.button('Increment', on_click=increment_counter)

st.write('Count = ', st.session_state.count)

最后,貼一張官網介紹Streamlit的模型邏輯圖:

真的很喜歡這款產品,交互設計很贊👍

頁面布局

通常情況下,Streamlit默認居中展示,感覺比例是30%-40%-30%分布,所以若是不添加一些Widgets組件的情況下會顯得兩邊很空。

方法一:右上角Setting

這一操作等同於:st.set_page_config(layout="wide")
但是這樣設置后得到的又太寬了...


方法二:通過Markdown語法配置

st.markdown(
    f"""
    <style>
        .reportview-container .main .block-container{{
            max-width: {1800}px;
            padding-top: {10}rem;
            padding-right: {10}rem;
            padding-left: {10}rem;
            padding-bottom: {10}rem;
        }}
        .reportview-container .main {{
            color: white;
            background-color: black;
        }}
    </style>
    """
    ,unsafe_allow_html=True,
)

方法三:通過st.beta_container等方式進行布局
嚴格意義上來講,這個並不是進行區域擴展的方法,只是將默認區域再分塊,類似於前端HTML中的div用法。

import streamlit as st
from string import ascii_uppercase, digits
from random import choices


st.header('Test Layout')
img_base = "https://www.htmlcsscolor.com/preview/128x128/{0}.png"
colors = (''.join(choices(ascii_uppercase[:6] + digits, k=6)) for _ in range(100))

with st.beta_container():
    left_col, right_col = st.beta_columns(2)
    left_col.image(img_base.format('D32166'), use_column_width=True)  # 若是不進行配置,間距大會比較丑
    right_col.write('placeholder')

with st.beta_container():
    for col in st.beta_columns(3):
        col.image(img_base.format(next(colors)), use_column_width=True)

with st.beta_container():
    for col in st.beta_columns(9):
        col.image(img_base.format(next(colors)), use_column_width=True)

得到:

可以看到各個container還是垂直布局,只是在不同的container中,水平分開了好幾個。


Ace Editor

可以在頁面內同步進行編輯的插件,可以看下參考資源5,挺好玩(但是網路不行時候加載不全...)

import streamlit as st
from streamlit_ace import st_ace

st.set_page_config(layout="wide")
st.header('Test Layout')


def main():
  with st.beta_container():
    left_col, right_col = st.beta_columns(2)
    with right_col:
      content = st_ace(language='python', key="ace")
    with left_col:
      st.write(content)
      # st.write([*streamlit_ace.LANGUAGES])


if __name__ == "__main__":
    main()

一個初步的帶編輯器的界面,但是似乎配置編譯器語言未成功:

其實還不如配合VS Code來得好,花里胡哨的,下回再看...

2021.7.15 填坑待續...


參考資源

1.Welcome to Streamlit Doc -- 跟着這個上往下走就行,有問題查查API部分
2.discuss 社區 -- 網不好進不去
3.New layout options for Streamlit
4.Lay your app
5.Streamlit-ace插件 -- 官方Demo
6.Streamlit:快速數據可視化界面工具:2021.9.15補充 這篇博文寫得挺詳細


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM