Build an asynchronous nutrition app on Streamlit
In this blog you will be guided through how Streamlit can be used to share a web app which consumes data from the Nutritionix API asynchronously using the httpx package in order to break down a meal into it’s key macro ingredients (protein, fat and carbohydrate).
Firstly, enjoy a demo of what we will be building:
Prerequisites: sign up for a free profile on Streamlit:
as well as on Nutritionix:
Obtain your free API keys from Nutritionix, they will be needed shortly.
Create a new Python module, named streamlit_app.py
and add it to a new GitHub repository named nutrition-planner
On streamlit.io
, deploy a new App that points to the URL of streamlit_app.py
. Next, visit the App Settings and go to Secrets where you will be storing the nutritionix API keys obtained in the previous step:
Returning to the streamlit_app.py
, insert (after installing) the necessary package imports:
In order for Streamlit to use these imports, you will need to add some of them to a requirements.txt
file:
Back to streamlit_app.py
, set a Streamlit title and description, adding your name:
Prompt your users for the number of key ingredients in the meal they wish to analyze:
Setting up a dictionary placeholder for the meal ingredients, looping over each of them in order to prompt their details (name, amount, unit) from your user, storing them back to the placeholder and validating that their datatypes are correct:
Set up the Nutritionix URL and load in your API keys as Streamlit secrets,
as part of the request header:
Prepare another dictionary placeholder, this time for the macro nutrient data:
nutrition = {"protein": 0, "fat": 0, "carbs": 0}
Now define an asynchronous function get_nutritionix
that for a given amount of a certain food ingredient will perform a HTTP post to lookup macro nutritional info in nutritionix and store it back to the nutrition
dictionary:
This will then get created as a task inside our next async function main
for every key ingredient. main
will be using the AsyncClient
from the httpx
package as a context manager named client
, allowing us to use a lower level API and only needing to send the headers once. The body sent will contain the user-provided ingredient info and a timezone. Finally, all tasks are gathered.
Set up timing with the time
package: start_time = time.time()
Then execute the main function asynchronously: asyncio.run(main())
Render the total meal macros as well as the total time spent on calling Nutritionix:
Finally, render a barplot with the macro results:
Giving a barplot such as the following:
You now have a fully functional nutrition app hosted on Streamlit!
The complete source code can be found here:
Try out the app here:
https://thenewthinktank-nutrition-planner-streamlit-app-sunft6.streamlitapp.com/
Considerations
The free plan on Nutritionix grants you a few hundred API calls per day,
so in case you would wish to scale your app further, there are also paid plans available.