「跟著黑蛋用Streamlit速成天文資料分析Web App」系列文[8]:再版系外行星資料表篩選器app,新增資料快取機制

黑蛋發現目前在系外行星資料表篩選器app中每操作一次篩選,都會再次呼叫get_exoplanet_table_by_astroquery()函式,以致於要再次等待資料表載入。他了解到這是因為Streamlit app是基於一個Python script執行結果所呈現的頁面,每在頁面中做一次操作,會更新Python script中的變數,進而重新執行整個Python script以更新頁面。黑蛋心想,每次都要等待同樣的資料重新載入,這會是一個蠻差的使用者體驗,他得研究看看是否能解決這個問題。

起初,黑蛋找到@st.cache這個decorator可以加在get_exoplanet_table_by_astroquery()函式上方,它會將函式回傳值(value),以及由函式名稱、函式內的程式碼、傳進函式中的參數等資訊所組合成的雜湊值(key),以key-value綁定儲存到快取記憶體中,當函式再次被呼叫時,會先檢查上述資訊的組合是否有變化,若無變化,則略過函式執行步驟,直接從記憶體中取得之前暫存的函式回傳值,以縮減等待時間。

不過,黑蛋進一步發現,Streamlit的開發團隊將會棄用@st.cache,如文件中的說明,因為@st.cache涵蓋不同的使用情境,導致它的程式較為複雜且會拖慢執行速度,所以目前將之拆分成兩個實驗性質的decorator:@st.experimental_memo@st.experimental_singleton,前者用來暫存經由函式計算、下載的資料,後者則是暫存非資料類的物件,例如session、資料庫連線等資訊,未來兩者都會成為正式的功能以取代@st.cache。

黑蛋選擇用@st.experimental_memo來快取get_exoplanet_table_by_astroquery()函式所回傳的資料表,並設定暫存效期為一天。此外,他還用了st.experimental_memo.clear(),讓使用者能為了取得最新的資料表而手動清除快取。如此一來,原本資料表會一直重新載入的問題就解決啦。

# exoplanet_table_filter.py 
import streamlit as st
from astroquery.ipac.nexsci.nasa_exoplanet_archive import NasaExoplanetArchive


@st.experimental_memo(ttl=86400, show_spinner=False)
def get_exoplanet_table_by_astroquery():
    table_name = 'pscomppars'
    columns = 'pl_name,hostname,sy_dist,pl_orbper,pl_bmasse,pl_rade,disc_year,discoverymethod'
    exoplanet_table = NasaExoplanetArchive.query_criteria(
        table=table_name, select=columns
    )
    exoplanet_table = exoplanet_table.to_pandas()
    exoplanet_table = exoplanet_table.rename(
        columns={
            'pl_name': '行星名稱',
            'hostname': '所屬恆星名稱',
            'sy_dist': '與地球的距離(單位:秒差距)',
            'pl_orbper': '行星軌道週期(單位:天)',
            'pl_bmasse': '行星質量(單位:地球質量)',
            'pl_rade': '行星半徑(單位:地球半徑)',
            'disc_year': '發現年份',
            'discoverymethod': '發現方法'
        }
    )
    exoplanet_table.sort_values(
        by='發現年份', ascending=False, inplace=True, ignore_index=True
    )

    return exoplanet_table

# 中略

if st.sidebar.button('清除資料表快取'):
    st.experimental_memo.clear()
    st.balloons()
    st.sidebar.success('已清除快取,請重新載入頁面')

此系列文由蘇羿豪撰寫,以「創用CC 姓名標示 4.0(CC BY 4.0)國際版授權條款」釋出。

Subscribe to 天文背包黑客
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.