Streamlit -Dynamic Web Pages with Python

Baertschi
3 min readMay 18, 2022

Did you know, you can create a web UI entirely in Python?

Streamlit is a python framework which allows you to write a dynamic web page in python.

With just two lines of python code you can get a running webpage

import streamlit as st
st.title('Hello World')

Run the script with:

streamlit run myScript.py

Streamlit offers a variety of widgets from buttons to sliders up to calendars. It’s possible to trigger python functions directly, make DB calls and display nicely formatted data with pandas.
Use your favorite library to display your data like Matplotlib, Plotly or many others charts

Line Chart

You can even install Streamlit over Anaconda.

https://coderzcolumn.com/tutorials/data-science/basic-dashboard-using-streamlit-and-matplotlib

Good to know and common problems:
However, the way Streamlit works is quite different compared to conventional Web-Apps (HTML/CSS/JavaScript/..)

Everityme an action is taken like pressing a button or navigating to another page the whole python code gets executed. Resulting in re-initializing all variables and losing the state.
While working with Streamlit there is no way around storing the state externally. A good solution would be to store the state in a DB like Redis or locally in a JSON file.

Issues i run into because I was not aware of this cycle:

Counting a variable by pressing a button:
A simple button with a count goes not over the value 1
Issue: every time the button gets pressed the whole script re-runs and initializes the count variable (resetting the variable)

Solution for Shared State:
Store the state of the button in an external JSON file like:

import streamlit as st

import os
import json

#check if file already exists, if not create a new file and add a dictionary to it
if not os.path.isfile('2.WebApp.json'):
with open('2.WebApp.json', 'w') as f:
json.dump({'clicks': 0}, f)

#initialize the value in the json wit the value from the clicks
with open('2.WebApp.json') as f:
counter = json.load(f)['clicks']

#count the variable if the button is clicked
if st.button('Click me with 2.WebApp'):
counter += 1

#output the current count as text
st.write(f'The button was clicked {counter} times')

#after incrementing store the new count value in the file befor we rerun the whole script
with open('2.WebApp.json', 'w') as f:
json.dump({'clicks': counter}, f)

Solution for Single State:
The session function from Streamlit will solve this issue, however if you close your browser or tab, the state will be lost.

import streamlit as st

if 'counter' not in st.session_state:
st.session_state.counter = 0
button = st.button('Increment')
if button:
st.session_state.counter += 1
st.write('Counter = ', st.session_state.counter)

For a more advanced solution you can store the state in a Key-Value Store DB like Redis.

Updating a live chart with values from a data-stream:
The code gets only executed by taking an action like pressing a button therefore new data will not be presented in the dashboard unless the whole page gets refreshed.

Solution:
There is no build in solution yet.
As a workaround we can add a dummy button with the name “Refresh” . Pressing this button will result in refreshing the whole page and loading the new data.

Executing a code/function only once:
Since every time the whole script gets executed all the functions get executed as well.
Problem i had:
I was using a blocking-UDP Socket which can be bound only once to a certain port. Streamlit re-runs the script all the time therefore this would result in an error since the port is already in use.

Solution:
Using the annotation @st.cache does prevent executing code multiple times and can therefore be misused to prevent a function to be re-executed every time a button is pressed.

import socket
import streamlit as st
st.header('Listening')UDP_IP = '127.0.0.1'
UDP_PORT = 1623
@st.cache
def bind_socket(ip,port):
logging.info('bind socket')
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.bind((ip, port))
return sock
sock = bind_socket(UDP_IP, UDP_PORT)

Learn how to handle State/State management in Streamlit her.

--

--