Module 7: Open Source Collaborative Development
Session 7C - Further Web Development with Streamlit
Sammi Rosser
“All That Jazz”
11th June 2024
facility location problems
Housekeeping
Recap
Last week we built a couple of Streamlit apps�
Recap
Last week we built a couple of Streamlit apps�
Recap
Last week we built a couple of Streamlit apps�
Plan for this week
We’re going to mainly focus on building an app for running a discrete event simulation
A lot of projects go down a DES route
Web apps are a very popular way to allow stakeholders to interact with these models
The principles translate well to a wide range of the techniques we’ve covered on the course!�
Plan for this week
They also allow us to practice�
Streamlit Recap
Let’s recap the fundamentals of building a Streamlit app.
Time to switch to VSCode!
Next Steps: A DES App
So now we hopefully remember the key parts of building and running a Streamlit app, we want to start thinking about how we can join this up with a DES model.
What might our output look like?
What we’re aiming for
Let’s remind ourselves of what a DES app might look like.
What we’re aiming for
We can provide users with a range of outputs.
What we’re aiming for
And we can start to build up to avoiding overwhelm while giving power users more control over the inputs...
What we’re aiming for
And the level of output they are comfortable with.
What we’re aiming for
The possibilities are endless!
https://simpy-visualisation.streamlit.app/Community_Booking_Model_Multistep
DES Recap
We will need to replace some of the inputs to our DES model with sliders, dropdowns and more.
We’ll also want to remind ourselves what we get out of our Streamlit models so we can provide some tables or graphs that our users could view and download.
So let’s go back several months and remind ourselves what precisely DES is and how a DES model is structured.
What is Discrete Event Simulation?
Discrete Event Simulation (DES) is a way of modelling �queueing problems
Healthcare in particular involves a lot of queuing problems!
What is Discrete Event Simulation?
Entities
👨🏽⚕️👨🏻⚕️👩🏿⚕️👩🏼⚕️🛏️🛏️🛏️
🤒😷🤕🤧🤢
flow through a pathway
using resources along the way
Arrive
Sign in with receptionist
Triaged
See nurse
See doctor
Additional Tests
Discharge
Coding a DES: SimPy
SimPy is a Python package that allows us to create powerful Discrete Event Simulation (DES) models.
It provides a series of building blocks for us to put together into highly customised discrete event simulations.
Structuring Simpy Models
There are multiple ways to structure a simpy model!
It’s a good idea to use object-oriented programming (OOP).�
Classes
We strongly recommend structuring SimPy models in an Object Oriented way. Specifically, we’re going to have 4 different classes.
g Class <- our PARAMETERS
This is a special class that will store our global level parameters for the model.
Unlike most OOP cases, we won’t create an instance of this class (hence the lower case) - we’ll just refer to the blueprint directly.
Model <- our PATHWAYS
This is the big one that represents the system that we are modelling (our clinic in this case).
It’ll have our generators, our patient journeys and more, and it’s where our SimPy environment (where everything lives) will be kept.
We’ll also have a method for one run of the model.
Patient <- our ENTITY
This class will represent our entity - patients.
Patients will carry with them information that we can record to and / or read from (e.g. an ID, how long they spent queuing, their condition etc).
If we had more than one entity, we’d need a class for each.
Trial <- what we run
This class will represent a batch of runs of our simulation, and will have methods to run a trial, extract results etc.
Runs and Trials
A single run of a model for a simulated period of time is known as a run.
A batch of multiple runs with the same parameter values is known as a trial.
The g Class
When making a Streamlit app of your DES model, most of the changes to your DES code will be in the g class.
You can basically leave the other three classes untouched!
Let’s head over to the code and take a look at how we’d adapt a model.
g Class
This is a special class that will store our global level parameters for the model.
The g Class
Here’s our original g class.
It looks like we need to make use of some number inputs or some sliders.
The g Class
We will create an input for every parameter - here are two examples.
Before
After
Now we can change how our g class is written.
st.sidebar
We could put this in a column of our app - but a sidebar can be a nice way of organising inputs too.�https://bergam0t.github.io/streamlit_book/layout_sidebar.html
with st.sidebar:
st.header("I'm a sidebar")
st.write("We can use inputs our sidebar too.")
name = st.text_input("What's your name?", value=None)
Once we write a line of code that is not indented, this signals the beginning of code that will just appear in the main area of the streamlit app.
User Inputs: Common Examples
Note that the variable names below are just examples - you can use any variable name that makes sense for your app.
my_number = st.number_input(“Enter a number”)
my_short_text = st.text_input(“Enter your name”)
my_long_text = st.text_area(“Enter a story”)
my_slider = st.slider(“Choose a number between 1 and 100”)
my_selection = st.selectbox(“Select an option from the list”, [“Red”, “Blue”, “Green”])
Many widgets have multiple additional options like minimum and maximum values or default values - take a look at the Streamlit documentation.
https://docs.streamlit.io/develop/api-reference/widgets
The streamlit book also covers several key input types.
https://bergam0t.github.io/streamlit_book/text_numeric_and_selection_inputs.html
Displaying outputs
We can then use a range of different outputs to display tables and plots.
The main ones will be
st.dataframe()
st.plotly_chart()
st.metric()
Loading and displaying a dataframe
Dataframes are then just displayed with
st.dataframe(my_df)
If you want it to use the full space, use
st.dataframe(my_df, use_container_width=True)
Altering how the dataframe columns are displayed
We use the ‘column API’ to adjust the way column names and values are displayed.
You can use this for as many or as few columns as you like.
Check the documentation to see all available column types: https://docs.streamlit.io/develop/api-reference/data/st.column_config
Displaying charts
Charts can be built in the normal way, then displayed using the various streamlit functions.
e.g.
Plotly plots: st.plotly_plot(your_plotly_fig)
https://bergam0t.github.io/streamlit_book/interactive_charts.html
Displaying metrics
Metrics allow you to display a value and an optional comparison.
Arranging your dashboard using columns
For columns, you need to use the st.columns() function.
https://bergam0t.github.io/streamlit_book/layout_columns.html
�Inside the bracket, put the number of columns you want.
On the left of your equals, create the same number of variables as the number of columns you have asked streamlit for.
E.g.
col1, col2, col3 = st.columns(3)
col_a, col_b = st.columns(2)
Indent code to make it appear inside a given column.
with col1:
st.dataframe(my_dataframe)
with col2:
st.pyplot(fig)
Arranging your dashboard using tabs
For tabs, you need to use the st.tabs() function.
https://bergam0t.github.io/streamlit_book/layout_tabs.html
�Inside the bracket, put a list of as many strings as you want tabs.
On the left of your equals, create the same number of variables as the number of tabs you have asked streamlit for.
E.g.
tab1, tab2, tab3 = st.tabs([“My Graph”, “My Map”, “My dataframe”])
tab_a, tab_b = st.tabs([“Thing 1”, “Thing 2”])
Indent code to make it appear inside a given tab.
with tab1:
st.dataframe(my_dataframe)
with tab2:
st.pyplot(fig)
Arranging your dashboard using expanders
For collapsible sections, you need to use the st.expander() function.
https://bergam0t.github.io/streamlit_book/layout_expander.html
�Indent code to make it appear inside a given expander, passing the expander function the wording you want to display when the expander is in its collapsed state.
with st.expander(“Click to view the hidden dataframe”):
st.dataframe(my_dataframe)
Letting your dashboard use the full page width
As the first thing in your app after your initial library imports, use the st.set_page_config() function.
To this, pass the layout=”wide”
import streamlit as st
import pandas as pd
st.set_page_config(layout=”wide”)
st.title(“My app’s title”)
df = pd.read_csv(“my_df.csv”)
st.write(df)
etc.
Downloading dataframes
Dataframes can be downloaded in the following way.
https://bergam0t.github.io/streamlit_book/file_downloads_tabular.html
For a dataframe my_df:
st.download_button(
"Click here to download the dataframe as a csv file",
data=my_df.to_csv(index=False).encode('utf-8'),
file_name=f"output.csv",
mime="text/csv"
)
Downloading charts
Downloading charts uses a very similar syntax, but the layout varies slightly for different file types.
Interactive charts (plotly): https://bergam0t.github.io/streamlit_book/file_downloads_images_charts.html#plotly
st.plotly_chart(fig)
fig.write_html("plotly_chart.html")
with open("plotly_chart.html", "rb") as file:
st.download_button(
label='Download This Plot as an Interactive HTML file',
data=file,
file_name='my_plotly_plot.html',
mime='text/html'
)
Exercise 1: Fulfil your DEStiny
You’ve been provided with the more advanced version of the discrete event simulation from session 2B and your task is to create an app for running this.
I’ve updated this code slightly to add in some extra logging steps that will give you more potential for plots.
Before you start trying to adapt the code, run the provided code in an interactive window and take a look at the outputs it prints.
Exercise 1: Fulfil your DEStiny
Here is a diagram of the model!
Exercise 1: Fulfil your DEStiny
Adapt this code into a Streamlit app.
(NOTE - for now I’d recommend copying the DES code into your app or just adapting the code file into a Streamlit app. Importing the individual classes is a little more complex and covered in the next part!)
Your app should allow people to change
You can place these parameters anywhere (e.g. main screen, sidebar).
It should then display some (or all) of the charts and summary values from the original file
Exercise 1: Fulfil your DEStiny
You can also explore some additional ways to enhance your app.
Part 2
Now we’re going to take a look at some features that will help you organise larger apps, as well as making them look how you want them to!
Run Buttons
We can prevent the app from running until we have finished changing all our parameters!
The first line makes a button.
The next lines then will only execute when the user presses the button.
Good Organisation Habits
It’s a good idea to try and separate your code out.
It’s easier to keep track of what’s going on (for you and other people!)
Let’s take a look at doing that.
Good Organisation Habits
Here I’ve split my code into
app.py
and
des_classes.py
I’ve also created a blank file
called �__init__.py �that is important for allowing us to import functions and classes from one file into another.
You don’t need to put anything at all in the __init__.py file - it’s just so Python understands that there’s files in this folder that can be imported from.
Good Organisation Habits
In my des_classes.py file I have the simpy, pandas and random imports.
I might also have additional packages like re and numpy here in more complex simulation models.
It defines the following classes:
In this case, I put the code for the plots into the app (user interface) file discussed on the next slide - though I could split those out into functions in their own file too!
Good Organisation Habits
In my app.py file I import streamlit and anything else I use specifically in this file, like plotly and pandas.
Then I import the g and Trial classes from our new file.
Notice I don’t need to use .py after the file name when importing.
Now instead of setting up the g class using the variables relating to our inputs, I instead overwrite the values of the g class.
Module 7: Open Source Collaborative Development
Session 7C - Further Web Development with Streamlit
Sammi Rosser
“All That Jazz”
Multipage Apps
As your app becomes bigger and more complex, it can be beneficial to split it out into multiple pages.
Multipage Apps
Each page of a multipage app can be quite separate from the others.
This is good as our apps get more complex - it can separate out things we don’t want to run at the same time.
Used well, it can also make it easier for our users to interact with the app and find what they’re looking for.
The main downside is that you can’t just create a variable on one page and use it on another
Multipage Apps
There are a few supported ways to set up multipage apps.
We’re going to look at Streamlit’s favoured way, which has the benefits of being very flexible.
Note that some of Streamlit’s documentation uses the old method, which is still fine but looks a bit different from this!
Multipage Apps: Example app.py
The key parts of your app.py are
Multipage Apps: Icons
We can also use an optional ‘icon’ parameter to add an icon into the navigation bar for some of all of our pages.
Just replace the bit after the / with the relevant name from here: https://mui.com/material-ui/material-icons/
Theming with config.toml
There are a few parts of Streamlit’s theming that we can officially change using a configuration file.
This file needs to be called config.toml and lives inside a subfolder called .streamlit
The config.toml file contains a variable number of parameters.
It can determine whether the default colourscheme is light or dark, and whether the default streamlit colours are overridden.
Populating config.toml
You can create a template config.toml from within streamlit, then paste the output into a config.toml file you create yourself.
Logos
Streamlit has basic support for small logos in your app.
It will look for a file you specify relative to the currently running streamlit file
Logos
The logo will appear in the top left of your app.
If it’s a multi page app, it will appear at the top of the sidebar.
Ideally, your logo should be close to 24 pixels tall by 240 pixels wide.
Logos
It is possible to include larger logos through more advanced tricks, but they are fragile and prone to breaking as changes are made to the Streamlit library.
If you want to experiment with this yourself, take a look at the add_logo() function in this file: https://github.com/hsma-programme/Teaching_DES_Concepts_Streamlit/blob/main/helper_functions.py
Custom CSS
To customise the look of your app much more than this, we need to turn to custom css.
CSS stands for ‘cascading style sheets’ and is a language used for theming much of the web!
We can create our own .css file and force Streamlit to load it in.
Custom CSS
What does the .css file look like??
Custom CSS - Result
Without style.css imported
With style.css imported
Exercise 2: DEStiny’s Child
It’s time to enhance our DES app a bit! We’ll work on this for 25 minutes.
Take a copy of your original version first and store it somewhere safe!
Do these steps in the order listed, and take the time to make sure it’s working after each step.
Bonus:�
Part 3
In the next section, we’re going to tackle some advanced features that will help you as your app starts to become more complex.
Caching
Session State
Callbacks
Partial Reruns (Fragments)
Caching
We often want to load data files into Streamlit.
There are two main issues we might run into.
Caching
By using the
@st.cache_data
decorator, Streamlit will intelligently handle the loading in of datasets to minimize unnecessary reloads and memory use.
To switch from doing a standard data import to using caching, we
We can then just use our dataframe like normal - Streamlit will handle the awkward bits.
Caching
Without Caching
Loading in the same dataset with caching
Caching Types: Data vs Resources
Caching can also be used for other large files - for example, if you wanted to load in a trained machine learning model that’s the same for all users who will interact with your app.
As a general rule:
@st.cache_data
@st.cache_resource
https://docs.streamlit.io/develop/concepts/architecture/caching#deciding-which-caching-decorator-to-use
It’s not always obvious which to use, so head to the Streamlit documentation if you’re a bit unsure.
More Advanced Caching
While using caching for the initial load of a dataframe, it can also make sense to use it for other long-running functions.
Like normal functions, functions for caching can accept parameters.
Streamlit will be able to look at the parameters passed in and tell whether it should �
* There are a few complexities around parameters that you may want to look into if using this in your own app: https://docs.streamlit.io/develop/concepts/architecture/caching#excluding-input-parameters
Caching Settings: TTL
When you choose to cache something, you can add in some additional settings to make the cache as effective as possible for your particular situation.
ttl (time to live)
TTL determines how long to keep cached data before rerunning it.
For example, if data is likely to change over time, you could set the ttl parameter to set the number of seconds to keep cached data for.
@st.cache_data(ttl=3600)
def your_function_here():
…
This also prevents your cache from becoming very large.
Caching Settings: max_entries
When you choose to cache something, you can add in some additional settings to make the cache as effective as possible for your particular situation.
max_entries
Once the cache contains the maximum number of objects you have specified, the oldest ones will be deleted to make way for new ones.
@st.cache_data(max_entries=10)
def your_function_here():
…
This also prevents your cache from becoming very large.
Session State
One limitation we’ve mentioned of multipage apps is that variables do not persist across the different pages.
Once you switch pages, all of that information is lost!
However - you can use session state to remember things across multiple pages or multiple runs of the same app.
It doesn’t help with remembering information when leaving or fully reloading the page.
Session State - Initialisation
First, we need to initialise the variable with a default value if it doesn’t already exist.
You need to do this on every page of your app where you will do either of the following:
Session State - Setting
Session state can be used to store a range of things.
It can store the input given in a user input widget:
Or the result of a calculation (whether that’s a number, a dataframe, a graph, or something else)
The thing you’re saving to the state could itself optionally use something stored in the session state!
Session State - Using
You can then access the session state key regardless of the page you are using it on!
Just remember - you need to check for whether the key exists in the session state anywhere you are setting or using the key, and set a default value for it if it doesn’t already exist.
When your app is deployed, a user could open the app on a page that means they are trying to view the stored session state key before they’ve had a chance to actually input a value - so think about how you could use conditional logic (if/elif/else) to handle this gracefully.
Callbacks
Callbacks are custom functions that will execute when a user interacts with an input.
They are often used in conjunction with session state.
For example - we could increment a counter every time the user clicks on a button.
In standard Streamlit, this would be impossible because it would forget that you clicked the button every time you did so!
Callbacks + session state get around that problem.
Callbacks - Code
To begin, we initialise our session state variable like before.
Next, we define our callback function.
We associate the callback with the relevant input, using the ‘on_click’ or ‘on_change’ parameter as appropriate.
Finally, we use our session state variable as we want to!
Session State and Callbacks
While the ways I’ve mentioned here should work in most simple cases, you may want to take a look into the documentation to fully get your head around the power of state and callbacks.
https://docs.streamlit.io/develop/api-reference/caching-and-state/st.session_state
* It’s technically better practice to use the on_change callback if you’re storing the value of an input widget in session state - but just assigning it directly works in most cases
Partial Reruns (fragments)
Partial reruns are a fairly new feature in Streamlit that allow you to break out of the traditional top-to-bottom rerun pattern of a Streamlit app.
It requires you to group together the inputs that should affect a given output into a single function, adding the @st.fragment decorator.
You then just call this function in your code to add in all of the relevant bits, and Streamlit handles the running!
Partial Reruns (fragments)
Here we have an example without the use of partial reruns.
The whole app reruns every time you change an input, even though the inputs only affect the graph directly underneath them.
Partial Reruns (fragments)
Here, we’ve split the two sets of inputs and outputs into two separate functions with the @st.fragment decorator. Notice how only half the screen fades out when an input is used!
Partial Reruns (fragments)
Function 1
@st.fragment
def this_bar_chart():
species = st.selectbox(...)
st.plotly_chart(...)
with col_1:
this_bar_chart()
Function 2
@st.fragment
def this_scatterplot():
input_1 = st.selectbox(...)
input_2 = st.selectbox(...)
input_3 = st.selectbox(...)
st.plotly_chart(...)
with col_2:
this_scatterplot()
Exercise 3: DESpite Everything, It’s Still You
Let’s now make our app really powerful! We’re going to work with a new Streamlit app that works out the estimated demand for an area given its demographic features*, make it more efficient, and then incorporate it into our main app.
We’ll first take a look at the new Streamlit app we’re going to work with.�
* this is just a dummy app to show what’s possible - it’s not using a proper method to estimate the demand!�
Exercise 3: DESpite Everything, It’s Still You
�Challenge Activity
Try saving some key outputs from each model run to the session state and use this to display a comparison of the outputs across these multiple runs�
Deployment
Now it’s time for the final step
(of the first iteration of your tool)
Getting it out there so other people can use it!
Deployment Methods
There are a couple of key routes you might be interested in for Streamlit app deployment
We’ll focus on this today
How Does a Deployed Web App Work?
Are you being served?
“A server is a computer or system that provides resources, data, services, or programs to other computers, known as clients, over a network.”
Any computer that’s connected to an intranet or the internet can act as a server - they may just vary in how good they are at the job and how exactly they go about it!
Are you being served?
https://commons.wikimedia.org/wiki/File:A_view_of_the_server_room_at_The_National_Archives.jpg
https://en.wikipedia.org/wiki/Mini_PC#/media/File:2009_Taipei_IT_Month_Day1_Acer_Aspire_Revo.jpg
It doesn’t just have to be sitting in a big server room that your organisation may (or may not) have…
Or even a microcomputer…
It can be any old computer…
Are you being served?
Or maybe it’s on someone else’s server, running in its own little virtual machine.
Streamlit Community Cloud
Streamlit community cloud is a completely free hosting platform that’s great for getting some apps out there.
If your app uses data that is not sensitive, then community cloud is often the easiest option available to you.
Streamlit Community Cloud
Any app that is hosted on github can be deployed in just a few clicks.
It gets its own customisable, persistent URL that can be shared with users.
Streamlit Community Cloud
There are a few limitations:
Streamlit Community Cloud
You might be able to publish more than you think!
Talk to people in your organisation about how sensitive the data actually is.
Are the default parameters for a DES actually sensitive?
What about travel time data at LSOA level?
Streamlit Community Cloud
https://efit-tool.streamlit.app/?utm_medium=oembed
Streamlit Community Cloud
https://hsma4cardiac.streamlit.app/
Streamlit Community Cloud
IT’S ALWAYS BEST TO ASK - don’t get yourself in trouble!
DONE
DONE
Requirements and Python Versions
Local Hosting
Docker
Bringing it closer to home
Pyodide: Benefits and Downsides
Stlite
The stlite framework brings the power of pyodide to Streamlit.
With (fairly) minimal modification, your web app becomes something that runs in the user’s browser!
Paired with github pages - which can be entirely free hosting - you can create websites that can deal with high concurrent traffic.
Stlite
We won’t go into details of stlite, but there’s an example of a complex multipage stlite app in this repository:
https://github.com/hsma-programme/Teaching_DES_Concepts_Streamlit
The key difference is having an index.html file that controls various aspects.
The stlite github provides a simpler single-page example too:
Stlite → .exe
In fact, you can take stlite even further and use it to create an executable file!
(though you may well end up with even more resistance from your organisation to this approach…)
It’s a bit more complex and may require getting some additional software approved to be able to do this.
If this sounds of interest to you, take a look at the following links:
All aboard the Enterprise
If you’re lucky enough to be working in a progressive organisation, you may have access to a service like Posit Connect, Plotly Dash Enterprise or Snowflake.
These services massively simplify the deployment and hosting of Streamlit apps, along with a series of bells and whistles like permission management/user authentication support.
https://en.wikipedia.org/wiki/USS_Enterprise_%28NCC-1701-A%29
It usually means someone else has already dealt with (most of) the messy stuff around secure sharing of data.
All aboard the Enterprise
For example, from posit connect, you can deploy Streamlit apps with just a few lines - as well as Shiny apps (in R or Python), Quarto documents (with scheduled refresh), Dash apps…
https://posit.co/blog/what-can-you-publish-with-posit-connect/
Name Your Price
Price - and/or the way pricing is calculated - can often be a barrier for organisations.
E.g. the ‘enhanced’ tier of Posit Connect
However - the efficiency savings by working with a tool like this have the potential to be huge.
Posit in particular have some history of working with NHS organisations to make pricing available that will work.
Anyone using these?
Shout out or pop it in the chat!
Recap: Version Control
We’re now going to go through the process of uploading our app to the community cloud.
This will involve a few key steps
requirements.txt
If your app only uses Streamlit, pandas and numpy, then you don’t strictly need to provide a requirements.txt file - though it’s still good practice to do so as it ensures you are in control of the versions in use and your app is less likely to break over time!
Otherwise, place a requirements.txt file in one of two places:
Exercise 4 contains a simple requirements file that should cover the main files from today, but you’ll want to use the main one from the environment folder if you want to deploy your wordcloud app from last week.
RECAP: Creating a repository
We have two broad options when we are working with repositories - create our own or work on someone else’s.
We’ll explore the latter more later. For now, let’s look at how we create a brand new repository. This is what we want to do when we start a new coding project.
First, we need to create a new folder that will store our repository on our local drive (note - you may run into issues if you try to do this on cloud storage).
RECAP: Creating a repository
Now let’s go into VSCode, and click the Source Control button on the left sidebar. This will open a panel asking if we want to open a folder or clone a repository.
For now, we’ll open a folder - the one we created a moment ago. Find the folder on your computer, double click into it, and then push the Select Folder button. You’ll be asked if you trust the authors of the files in the folder. Hopefully you trust yourself…
RECAP: Initialising a repository
Now we’ve selected the folder, we need to initialise the repository. This basically means that we create a new Git repository based on the files in our directory.
Our directory is currently empty - but you can do this for a folder that already has files in it. If there are files already there, Git will note that they exist but it won’t begin tracking them for future changes until we tell it to do so.
If we were using a command line interface, we’d call the command git init. But as we’re using VSCode, we simply click the Initialize Repository button that now appears in our Source Control panel.
RECAP: Untracked Files
Let’s add some code to our repository. I’m going to create a new .py file and save it in this directory, with the following code in it :
Once the code is saved you’ll notice two things :
The U indicates that this file is Untracked. This means that Git knows that the file exists in the repository, but it’s not currently tracking changes made to it.
RECAP: Staging
To tell Git we want it to start tracking changes, we need to tell it we want to include it in the next commit. To do that, we need to first stage the file. Recall the flow we talked about earlier :
RECAP: Staging
We can stage multiple files at once before committing our changes. But for now, we’re just going to stage our one and only file.
In a command line interface, we’d use git add. In VSCode, we simply click the + button next to the file(s) we want to stage in the Source Control panel.
Once we do this, we see that the file is added to the Staged Changes list in the panel. This means the file will be included in the next commit.
RECAP: Discarding Changes
If we want to discard changes we’ve made (ie reverse the staging), we can click the - button next to the file (or group of files).
If we have made changes to multiple files, we can stage all files that have changes at once by clicking the + button next to the “Changes” title of the list
RECAP: Commit
Once a file(s) has been staged, we can, when we’re ready, commit the changes to the repository. To do this, we need to supply a commit message. This is a short description of what the commit represents (ie what you’ve added / changed etc).
Commit messages should be concise, but also specific, so that someone else (or you, later down the road) can understand what this “snapshot” of changes represents.
Tip (thanks Tom) : you might consider splitting your commit message into two parts – 1) the type of commit you’re making (eg an initial upload of a file, a bug fix, upload of some documentation etc) and 2) the description of changes.
e.g “INIT: add my_calc.py” clearly tells us that this is an initial upload of a file, and the file that was uploaded was my_calc.py. Feel free to use your own style, but make sure it is consistent and that someone else could understand it!
RECAP: Commit
To commit all of our staged changes in VSCode, we simply type our commit message in the message box at the top of the Source Control panel, and then click the big “Commit” button.
(If you forget to add a message before clicking the button, this is where you’ll be taken to your chosen editor and will need to enter your message on a non commented line - eg line 12 on the screenshot below)
RECAP: Commit
Once you’ve committed your staged changes, you’ll see that (mostly) everything disappears from your Source Control panel. That’s because there are now no staged changes waiting to be committed. This is known as having a clean working tree.
Note : if you have changes that have not yet been staged, or untracked files, they’ll still appear here - you won’t have a clean working tree if that’s the case. The tree will also become “dirty” again as soon as you start modifying and / or adding files to a clean working tree.
RECAP: Publishing an existing repo
Let’s first look at how we’d publish an existing local repository (in our example, the one we’ve created today) on GitHub using VSCode.
To do this, we’re going to publish our main branch on GitHub.
Using the big “Publish Branch” button in the Source Control Panel.
I bet you guessed didn’t you?
We’ll make sure we’re in the main branch of our repo first, and then click the button.
RECAP: Publishing an existing repo
When we do this, if this is our first time using GitHub from VSCode, the following will appear. We need to click “Allow”.
RECAP: Publishing an existing repo
We’ll then get some authentication messages from GitHub that we’ll need to follow, including using our passkey. Note : I have my passkey setup so that it is linked to my Windows PIN authentication, so my authentication may be different to yours (and likely won’t appear during the session as I’m already authenticated). We’ll also be asked whether we want to publish to a private or public repository - I’m going to make mine public. By default, the name of the repo will be the same as the local one - you can change it, but I’d recommend you don’t.
In this case, make it public.
RECAP: Publishing an existing repo
When we go to publish the branch, if this is our first time publishing, we’ll get more authentication requests will need to go through and allow (don’t worry, this only happens once).
RECAP: Publishing an existing repo
Eventually, after a lot of authentication, the branch will be published, and when we go back to VSCode, we’ll see the following :
Git Fetch grabs updates from a repository but doesn’t merge them (it basically says “Here’s some updates, do you want to do something with them?”). My advice is to say “No” to VSCode doing this periodically, at least initially in your Git journeys (I’ve also heard reports that the VSCode periodic fetch can be a bit problematic)
Publishing to Community Cloud
Now we want to head over to the streamlit site: https://streamlit.io/
Choose ‘sign up’
Publishing to Community Cloud
Click ‘Continue to sign-in’
Publishing to Community Cloud
Sign up using any of the provided options
You will need to link up with your github account in a later step regardless of which option you choose here
You may need to enter a code in the next step to verify your email address, and enter some additional details to finish setting up your account.
Publishing to Community Cloud
Click ‘create app’
Publishing to Community Cloud
You’ll now be asked to connect to your GitHub account
Publishing to Community Cloud
Click
‘Authorize Streamlit’
Publishing to Community Cloud
Choose ‘Yup, I have an app’
Publishing to Community Cloud
Fill in the details as appropriate - various drop-downs will appear to help you.
This needs to be the name of the file you’ve been running in the terminal to launch your app during testing
When you’re done, click ‘deploy’ and enjoy your new app!
Publishing to Community Cloud
In the advanced settings, you can change the Python version your app runs on.
You can’t change this later!
You can also provide ‘secrets’ here, which is useful for things like database connections.
(still, be careful about what you share!)
Publishing to Community Cloud
When you’re done, click ‘deploy’ and enjoy your new app!
Publishing to Community Cloud
Once you’ve got all of this set up, in future, an easy way to publish to the community cloud is to run you app from the command line (after first publishing the repository on github) and choose ‘deploy’ from the top right.
This will pre-fill most of those details for you.
Streamlit Community Cloud
Once you’ve made a few apps, you’ll be provided with a list of all of your apps so you can manage various aspects of them.
Streamlit Community Cloud
Clicking on the three dots at the far right allows you to change various settings.
Streamlit Community Cloud
You can even have one ‘private’ app (though bear in mind that it is still published/hosted on external servers)
Exercise 4: Take Me To The Clouds Above
The final task of the day is deploying an app.
If you finish this,