初體驗
官網很好看:傳送門
快速安裝: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補充 這篇博文寫得挺詳細
