Deploy Streamlit to Azure Container Apps with IAC and CICD - Creating a Streamlit Application
In this post I will go over the Python code for the a simple 4 page application that demonstrates some of the key capabilities of streamlit.
This post is part 2 of a series of posts where I will write about my solution for getting a streamlit application deployed to Azure Container Apps with IAC and CICD.
The code repository for this tutorial is available on my GitHub repo streamlit-azure-container-app.
If you would like to check out the application before continuining with the post, take a look over at https://streamlit.jarrodlilkendey.com.
Creating a Streamlit Application
The streamlit application that I am creating is fairly simple. It is a 4 page web application with a navigation side bar. The pages are described in more detail in the sections below.
Streamlit Dependencies
There are two dependencies required to support this streamlit application, they are defined in the requirements.txt file.
1
2
streamlit==1.48.1
streamlit[charts]
Before you download the dependencies, the nest practice is to first set up a Python virtual environment.
This can be done with the commands below.
1
2
3
4
5
6
7
8
9
10
11
12
13
# create virtual environment
python -m venv .venv
# Windows command prompt
.venv\Scripts\activate
# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS and Linux
source .venv/bin/activate
From within the virtual environment, to download the dependencies using pip3 and the requirements.txt file use the following command.
1
pip3 install -r requirements.txt
The Home Page
The Home page provides links off to the 3 other pages in the streamlit application.
1
2
3
4
5
6
7
import streamlit as st
st.title("Home")
st.page_link("dataframes.py", label="Pandas dataframes with streamlit", icon="👨💻")
st.page_link("inputs.py", label="Inputs supported by streamlit", icon="⌨️")
st.page_link("visuals.py", label="Streamlit visualisations", icon="📊")
All of these pages are also linked in the navigation side bar along with the Home page itself.
The Dataframes Page
The dataframes page demonstrates the capabilities of using pandas dataframes with streamlit for CSV that are already uploaded or selected from a CSV file hosted within the streamlit application.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import streamlit as st
import pandas as pd
import os
st.title("Pandas dataframes with streamlit")
st.write("Load a CSV file into a pandas dataframe to display with streamlit")
file_option = st.radio(
"CSV file option",
["Use a sample file", "Upload my CSV"],
)
def render_dataframe_with_statistics(file):
df = pd.read_csv(file)
st.write("### Data Preview")
st.dataframe(df)
st.write("### Summary Statistics")
st.write(df.describe())
if file_option == "Upload my CSV":
uploaded_file = st.file_uploader("Choose a file")
if uploaded_file is not None:
render_dataframe_with_statistics(uploaded_file)
if file_option == "Use a sample file":
sample_csv_file_path = st.selectbox(
"Sample CSV file",
("data/csv/action_movies.csv", "data/csv/south_park_characters.csv", "data/csv/sample_weather_data.csv"),
index=None,
placeholder="Select sample CSV file..."
)
st.write("You selected:", sample_csv_file_path)
if sample_csv_file_path is not None:
if os.path.exists(sample_csv_file_path):
render_dataframe_with_statistics(sample_csv_file_path)
else:
st.error(f"File not found at {sample_csv_file_path}")
The Inputs Page
The inputs page demostrates a sub selection of the input elements supported by streamlit.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import streamlit as st
import datetime
st.title("Inputs supported by streamlit")
st.header("button", divider=True)
left, middle, right = st.columns(3)
if left.button("Plain button", width="stretch"):
left.markdown("You clicked the plain button.")
if middle.button("Emoji button", icon="😃", width="stretch"):
middle.markdown("You clicked the emoji button.")
if right.button("Material button", icon=":material/mood:", width="stretch"):
right.markdown("You clicked the Material button.")
st.header("checkbox", divider=True)
agree = st.checkbox("I agree")
if agree:
st.write("Great!")
st.header("radio", divider=True)
genre = st.radio(
"What's your favorite movie genre",
[":rainbow[Comedy]", "***Drama***", "Documentary :movie_camera:"],
index=None,
)
st.write("You selected:", genre)
st.header("selectbox", divider=True)
option = st.selectbox(
"How would you like to be contacted?",
("Email", "Home phone", "Mobile phone"),
)
st.write("You selected:", option)
st.header("number_input", divider=True)
number = st.number_input("Insert a number")
st.write("The current number is ", number)
st.header("date_input", divider=True)
d = st.date_input("When's your birthday", datetime.date(2019, 7, 6))
st.write("Your birthday is:", d)
st.header("time_input", divider=True)
t = st.time_input("Set an alarm for", datetime.time(8, 45))
st.write("Alarm is set for", t)
st.header("text_input", divider=True)
title = st.text_input("Movie title", "Life of Brian")
st.write("The current movie title is", title)
The Visuals Page
The visuals page demonstrates a selection of visualisations within streamlit using a variety of python visualisation libraries
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import streamlit as st
import altair as alt
import pandas as pd
import streamlit as st
from numpy.random import default_rng as rng
import plotly.express as px
import pydeck
import matplotlib.pyplot as plt
st.title("Visualisations")
st.header("altair_chart", divider=True)
df = pd.DataFrame(rng(0).standard_normal((60, 3)), columns=["a", "b", "c"])
chart = (
alt.Chart(df)
.mark_circle()
.encode(x="a", y="b", size="c", color="c", tooltip=["a", "b", "c"])
)
st.altair_chart(chart)
st.header("graphviz_chart", divider=True)
st.graphviz_chart('''
digraph {
run -> intr
intr -> runbl
runbl -> run
run -> kernel
kernel -> zombie
kernel -> sleep
kernel -> runmem
sleep -> swap
swap -> runswap
runswap -> new
runswap -> runmem
new -> runmem
sleep -> runmem
}
''')
st.header("plotly_chart", divider=True)
plotly_df = px.data.iris()
fig = px.scatter(plotly_df, x="sepal_width", y="sepal_length")
event = st.plotly_chart(fig, key="iris", on_select="rerun")
st.header("pydeck_chart", divider=True)
capitals = pd.read_csv(
"data/csv/capitals.csv",
header=0,
names=[
"Capital",
"State",
"Abbreviation",
"Latitude",
"Longitude",
"Population",
],
)
capitals["size"] = capitals.Population / 10
point_layer = pydeck.Layer(
"ScatterplotLayer",
data=capitals,
id="capital-cities",
get_position=["Longitude", "Latitude"],
get_color="[255, 75, 75]",
pickable=True,
auto_highlight=True,
get_radius="size",
)
view_state = pydeck.ViewState(
latitude=40, longitude=-117, controller=True, zoom=2.4, pitch=30
)
chart = pydeck.Deck(
point_layer,
initial_view_state=view_state,
tooltip={"text": "{Capital}, {Abbreviation}\nPopulation: {Population}"},
)
event = st.pydeck_chart(chart, on_select="rerun", selection_mode="multi-object")
st.header("pyplot", divider=True)
arr = rng(0).normal(1, 1, size=100)
fig, ax = plt.subplots()
ax.hist(arr, bins=20)
st.pyplot(fig)
st.header("vega_lite_chart", divider=True)
st.vega_lite_chart(
df,
{
"mark": {"type": "circle", "tooltip": True},
"encoding": {
"x": {"field": "a", "type": "quantitative"},
"y": {"field": "b", "type": "quantitative"},
"size": {"field": "c", "type": "quantitative"},
"color": {"field": "c", "type": "quantitative"},
},
},
)
The Application
The streamlit app.py file containing the main file for running the streamlit application, it defines adds the 4 pages to a navigation bar then runs the application.
1
2
3
4
5
6
7
8
9
10
11
12
13
import streamlit as st
# Define the pages
home_page = st.Page("home.py", title="Home Page", icon="🏠")
dataframes_page = st.Page("dataframes.py", title="Dataframes", icon="👨💻")
inputs_page = st.Page("inputs.py", title="Inputs", icon="⌨️")
visuals_page = st.Page("visuals.py", title="Visualisations", icon="📊")
# Set up navigation
pg = st.navigation([home_page, dataframes_page, inputs_page, visuals_page])
# Run the selected page
pg.run()
You can now run the streamlit app using the following command.
1
streamlit run app.py
The application should be accessible in the browser on localhost on port 8501.
Related Posts
This post is part 2 of a series of posts where I will write about my solution for getting a streamlit application deployed to Azure Container Apps with IAC and CICD.
See all of the posts included in this series below.
- Deploy Streamlit to Azure Container Apps with IAC and CICD - Overview
- Deploy Streamlit to Azure Container Apps with IAC and CICD - Creating a Streamlit Application
- Deploy Streamlit to Azure Container Apps with IAC and CICD - Containerizing the Application
- Deploy Streamlit to Azure Container Apps with IAC and CICD - Provision a Public Container Repository with Amazon ECR