Idenya
Model rerun me-reset setiap variabel biasa di setiap interaksi. Itulah sebabnya penghitung dari modul rerun selalu menampilkan 1. Untuk apa pun yang harus diingat aplikasi (total berjalan, item yang ditambahkan ke sebuah list, langkah wizard yang sedang dijalani pengguna), Streamlit menyediakan st.session_state: penyimpanan mirip dictionary yang bertahan di antara rerun selama tab browser pengguna masih terbuka.
Variabel biasa adalah papan tulis yang dihapus bersih sebelum setiap eksekusi. st.session_state adalah buku catatan di samping meja yang tetap di tempatnya. Setiap pengguna punya buku catatannya sendiri.
Penghitung, versi yang sudah diperbaiki
Ini penghitung dari modul 2 lagi, yang selalu menampilkan 1. Kali ini hitungannya disimpan di st.session_state, yang bertahan dari satu rerun ke rerun berikutnya:
import streamlit as st
if "count" not in st.session_state:
st.session_state.count = 0
if st.button("Add one"):
st.session_state.count += 1
st.write("Count:", st.session_state.count)
Tiga hal terjadi:
- Inisialisasi sekali:
if "count" not in st.session_statehanya bernilai benar di eksekusi paling pertama, jadicountdimulai dari 0 tepat sekali. - Update: klik menambahkan satu ke nilai yang tersimpan.
- Baca: tampilan memakai nilai yang tersimpan, yang sekarang bertahan di antara rerun.
st.session_state.count dan st.session_state["count"] adalah hal yang sama; pakai mana yang lebih enak dibaca. Pengecekan in dan .get("count", 0) berfungsi seperti pada dictionary.
Selalu inisialisasi session state dengan guard if key not in st.session_state. Tanpa itu, baris inisialisasi berjalan di setiap rerun dan menghapus nilai yang tersimpan, yang merupakan bug aslinya dalam penyamaran baru.
Mengingat sebuah list
"Daftar belanja" kecil berisi produk yang mau di-review:
import streamlit as st
if "watchlist" not in st.session_state:
st.session_state.watchlist = []
product = st.selectbox("Product", ["USB-C Hub", "Desk Lamp LED", "Pour-over Kettle", "Ceramic Mug"])
if st.button("Add to watchlist") and product not in st.session_state.watchlist:
st.session_state.watchlist.append(product)
if st.button("Clear"):
st.session_state.watchlist = []
st.write("Watchlist:", ", ".join(st.session_state.watchlist) or "empty")
List-nya tinggal di session state, jadi ia bertambah di setiap klik alih-alih mulai kosong setiap kali.
Widget dengan key sudah ada di session state
Beri sebuah widget key=, dan nilainya otomatis disimpan di bawah key itu:
import streamlit as st
st.slider("Discount (%)", 0, 50, 10, key="discount")
st.write("Discount from session state:", st.session_state.discount)
Ini berguna saat bagian lain dari aplikasi (sebuah callback, halaman lain) butuh nilai sebuah widget. Kamu juga bisa mengatur nilai widget lewat session state, tapi hanya sebelum widget itu digambar di eksekusi tersebut: mengaturnya sesudahnya memunculkan error, karena widget sudah menentukan nilainya untuk eksekusi ini.
Callback: jalankan kode saat sesuatu berubah
Widget menerima on_change (atau on_click untuk tombol): fungsi yang berjalan sebelum rerun script berikutnya. Callback adalah cara yang bersih untuk mengupdate state sebagai respons terhadap sebuah aksi:
import streamlit as st
if "count" not in st.session_state:
st.session_state.count = 0
def add(amount):
st.session_state.count += amount
def reset():
st.session_state.count = 0
st.button("+1", on_click=add, args=(1,))
st.button("+10", on_click=add, args=(10,))
st.button("Reset", on_click=reset)
st.metric("Count", st.session_state.count)
Kenapa repot? Karena callback berjalan sebelum script, metric-nya sudah menampilkan nilai baru di rerun itu. Dengan gaya if st.button(...), kode apa pun di atas tombol masih melihat nilai lama di eksekusi itu. Dengan beberapa tombol yang mengubah state yang sama, callback menjaga logikanya di fungsi-fungsi kecil bernama alih-alih rangkaian if.
args=(1,) memberikan argumen ke callback (perhatikan komanya: itu tuple).
Apa itu session state (dan apa yang bukan)
- Per pengguna, per tab browser. Dua orang yang memakai aplikasi punya state yang terpisah. Me-refresh halaman memulai sesi baru, dan state-nya hilang.
- Bukan database. Apa pun yang harus bertahan setelah refresh, atau dibagi antar pengguna, sebaiknya disimpan di file atau database (modul-modul selanjutnya).
- Bukan untuk data besar. Simpan hal-hal kecil (pilihan, id, list nama). Muat DataFrame besar dengan caching (modul berikutnya).
Mengapa ini penting untuk kode yang bersih
Session state adalah state global yang bisa diubah, jenis yang diusahakan kode bersih untuk tetap kecil dan eksplisit. Jaga tetap rapi: inisialisasi setiap key di satu tempat di bagian atas script (atau di fungsi init_state()), beri nama key dengan jelas, dan ubah state lewat fungsi callback kecil. Dengan begitu "di mana nilai ini berubah?" hanya punya satu jawaban.
Rangkuman
st.session_statemengingat nilai di antara rerun, per sesi pengguna.- Inisialisasi dengan
if "key" not in st.session_state:; baca dan tulis seperti dict atau attribute. - Widget dengan
key=otomatis menyimpan nilainya di session state. - Callback
on_click/on_change(denganargs=) mengupdate state sebelum rerun. - Session state hilang saat refresh: pakai file atau database untuk apa pun yang permanen, dan caching untuk data besar.