Idenya
Sebagian besar framework web membuatmu menulis "saat tombol ini diklik, update label itu". Streamlit tidak. Modelnya jauh lebih sederhana, dan sedikit mengejutkan:
Setiap kali pengguna berinteraksi dengan sebuah widget, Streamlit menjalankan ulang seluruh script-mu dari atas ke bawah, dengan widget itu sekarang mengembalikan nilai barunya.
Itu saja. Tidak ada callback yang harus disambungkan, tidak ada fungsi update. Script-mu adalah resep untuk halamannya, dan Streamlit memasaknya lagi setiap kali ada bahan yang berubah. Memahami satu aturan ini menjelaskan hampir semua yang dilakukan Streamlit, termasuk bagian-bagian yang membingungkan pemula.
Menjalankan aplikasi di komputermu
Di situs ini, tab App menjalankan script-mu di simulator. Di mesinmu sendiri, Streamlit adalah package Python biasa. Dengan uv:
uv add streamlit
uv run streamlit run app.py
Streamlit menjalankan server web lokal kecil dan membuka http://localhost:8501 di browser-mu. Saat kamu menyimpan app.py, halamannya menawarkan untuk menjalankan ulang; pilih Always rerun dan setiap penyimpanan langsung me-refresh aplikasinya. Terminal menampilkan error apa pun, begitu juga halamannya sendiri.
Melihat rerun terjadi
Cara terbaik memahami rerun adalah melihatnya langsung. Aplikasi kecil ini mencetak waktu persis saat dijalankan, lalu menanyakan namamu. Perhatikan waktunya sambil kamu memakainya:
import streamlit as st
from datetime import datetime
st.title("Rerun demo")
st.write("This script ran at", datetime.now().strftime("%H:%M:%S.%f")[:-3])
name = st.text_input("Your name")
st.write(f"Hello, {name or 'stranger'}!")
Tekan Try it, lalu ketik sebuah nama dan tekan Enter. Waktunya berubah: seluruh script berjalan lagi, bukan hanya baris sapaannya. Mengetik di kotak itu tidak "mengupdate sapaannya"; itu memicu eksekusi baru di mana st.text_input mengembalikan teksmu.
Widget mengembalikan nilai
Karena model rerun, sebuah widget hanyalah pemanggilan fungsi yang mengembalikan nilai saat ini:
import streamlit as st
discount = st.slider("Discount (%)", 0, 50, 10)
price = 320_000
st.write(f"Price after discount: Rp {price * (1 - discount / 100):,.0f}")
Di eksekusi pertama, slider mengembalikan default-nya (10). Saat pengguna menyeretnya ke 25, script dijalankan ulang dan st.slider mengembalikan 25. Kodemu tidak pernah bertanya "apakah slider-nya berubah?"; ia hanya memakai discount seperti variabel lainnya.
Tombol bernilai True tepat untuk satu eksekusi
Tombol mengembalikan True hanya pada eksekusi yang dipicu oleh kliknya, dan False di setiap eksekusi lainnya:
import streamlit as st
if st.button("Refresh data"):
st.success("Data refreshed!")
st.slider("Unrelated slider", 0, 10, 5)
Klik Refresh data: pesan sukses muncul. Sekarang geser slider-nya: pesannya hilang, karena eksekusi baru ini tidak dipicu oleh tombol. Itu perilaku yang benar, tapi mengejutkan orang yang mengira pesannya akan "tetap ada".
Penghitung yang tidak menghitung
Ini bug pemula yang paling terkenal:
import streamlit as st
count = 0
if st.button("Add one"):
count += 1
st.write("Count:", count)
Klik tiga kali: selalu menampilkan 1. Setiap eksekusi memulai script dari atas, jadi count = 0 berjalan lagi; kliknya menambah satu, dan selesai. Variabel biasa tidak bertahan antar eksekusi. Untuk mengingat nilai, Streamlit punya st.session_state, yang segera mendapat modulnya sendiri.
Berhenti lebih awal: st.stop
Kadang sisa halaman tidak masuk akal sampai pengguna memberikan input. st.stop() menghentikan eksekusi saat itu juga:
import streamlit as st
st.title("Customer lookup")
email = st.text_input("Customer email")
if not email:
st.info("Enter an email address to start.")
st.stop()
st.write(f"Looking up orders for **{email}**...")
Tanpa st.stop(), kamu harus mengindentasi seluruh sisa aplikasi di dalam sebuah if. Berhenti lebih awal menjaga kode utama tetap datar dan mudah dibaca, ide "guard clause" yang sama dari modul fungsi Python.
Apa arti model rerun bagimu
| Konsekuensi | Yang harus dilakukan |
|---|---|
| Setiap interaksi menjalankan ulang semuanya | jaga script tetap cepat; langkah yang lambat (memuat file, query) butuh caching |
| Variabel biasa di-reset setiap eksekusi | simpan hal yang perlu diingat di st.session_state |
Tombol bernilai True untuk satu eksekusi | pakai untuk aksi; pakai checkbox/toggle untuk state hidup/mati |
| Halaman dibangun ulang dari nol | tulis script dari atas ke bawah sesuai urutan halaman yang seharusnya muncul |
Modul-modul berikutnya membahas setiap alat ini. Untuk sekarang, yang penting adalah model mentalnya: script masuk, halaman keluar, lagi dan lagi.
Mengapa ini penting untuk kode yang bersih
Model rerun menghargai script yang bersih dan linear: baca input di atas, hitung, lalu tampilkan. Aplikasi yang ditulis seperti itu mudah diikuti karena urutan kode adalah urutan halaman. Saat sebuah aplikasi menjadi membingungkan, biasanya karena ia melawan modelnya (mencoba "mengupdate" sesuatu) alih-alih merangkulnya (menghitung ulang semuanya dari input saat ini).
Rangkuman
- Jalankan aplikasi secara lokal dengan
uv run streamlit run app.py. - Interaksi widget apa pun menjalankan ulang seluruh script dari atas.
- Widget adalah fungsi yang mengembalikan nilai saat ini.
- Tombol mengembalikan
Truehanya pada eksekusi yang dipicu oleh kliknya. - Variabel biasa di-reset setiap eksekusi;
st.session_state(nanti) mengingat nilai. st.stop()menghentikan eksekusi lebih awal; pakai sebagai guard clause.