Almost any web app that contains data needs a way to represent it succinctly and clearly to the user. However, most Python web development solutions do not provide an easy way to do this purely in . Python Thanks to the plethora of existing React components for creating graphs, an implementation for Python can be created to easily solve this problem. In this post, we’ll walk through how to build a web app purely in Python, which contains graphs that strike a balance between flexibility and ease of use. The graphs are easy to build but also easy to customize to your needs. For this project, we are going to use a new open-source dev tool called Reflex. 1. Getting started with your Python Web App If you face any problems here with installation check out more docs here: https://reflex.dev/docs/getting-started/installation/ $ pip install reflex $ reflex init 2. Creating an Interactive Graph In this example, we will create a live-streaming graph that updates every second with random data. We start by defining some initial data for our chart to use, as well as some imports we will use for the project: from typing import Any, Dict, List import reflex as rx import random import asyncio data = [ {"name": "A", "uv": 10, "pv": 110, "amt": 210}, {"name": "B", "uv": 20, "pv": 120, "amt": 230}, {"name": "C", "uv": 30, "pv": 120, "amt": 240}, {"name": "D", "uv": 30, "pv": 130, "amt": 210}, {"name": "E", "uv": 20, "pv": 140, "amt": 230}, {"name": "F", "uv": 40, "pv": 170, "amt": 250}, {"name": "G", "uv": 50, "pv": 190, "amt": 260}, ] Here stands for unique visitors, stands for page views and stands for amount. uv pv amt They are arbitrary values that we will use to populate our graph. Next, we define a class that will be used to store the data and update it with an event handler: StreamingState class StreamingState(rx.State): data: List[Dict[str, Any]] = data stream: bool = False def stop_stream(self): self.stream = False @rx.background async def start_stream(self): async with self: self.stream = True while self.stream: async with self: for i in range(len(self.data)): self.data[i]["uv"] = random.randint(0, 100) self.data[i]["pv"] = random.randint(100, 200) self.data[i]["amt"] = random.randint(200, 300) await asyncio.sleep(3) Here, we define a method that will stop the stream when called. We also define a method that will start the stream. We use the decorator to run the method in the background. This allows us to update the data without blocking the UI. stop_stream start_stream @rx.background Remember to use when updating the state in a background task. async with self: Finally, we will define our UI using Reflex's new graphing components. We pass the data from our class to the component and reference the data key we want to use in component. We also add a button to start and stop the stream. StreamingState area_chart area The result is a live updating graph that looks like this: The code for this graph is below: def index(): return rx.vstack( rx.recharts.area_chart( rx.recharts.area( data_key="pv", stroke="#82ca9d", fill="#82ca9d", type_="natural", ), rx.recharts.x_axis( data_key="name", ), rx.recharts.y_axis(), rx.recharts.legend(), data=StreamingState.data, width="100%", height=400, ), rx.hstack( rx.button( "Start Stream", on_click=StreamingState.start_stream, disabled=StreamingState.stream, ), rx.button( "Stop Stream", on_click=StreamingState.stop_stream, ), width="100%", ), width="100%", ) # Add state and page to the app. app = rx.App() app.add_page(index) app.compile() The last three lines define our app, add the graph component to the base route, and then compile our app. Now, we can run it with the terminal command. $ reflex run 3. Multiple Graphs We can add extra components to our chart to show the and data as well. We can also add a an component to show the data when we hover over the chart. area uv amt graphing_tooltip cartesian_grid Keep in mind the child coming first will be displayed in the back, so the order of the components matter. area The code for this graph is below: def index(): return rx.vstack( rx.recharts.area_chart( rx.recharts.area( data_key="pv", fill="#48BB78", stroke="#48BB78", type_="natural", ), rx.recharts.area( data_key="uv", fill="#F56565", stroke="#F56565", type_="natural", ), rx.recharts.area( data_key="amt", fill="#4299E1", stroke="#4299E1", type_="natural", ), rx.recharts.x_axis( data_key="name", ), rx.recharts.y_axis(), data=StreamingState.data, width="90%", height=400, ), rx.hstack( rx.button( "Start Stream", on_click=StreamingState.start_stream, is_disabled=StreamingState.stream, width="100%", color_scheme="green", ), rx.button( "Stop Stream", on_click=StreamingState.stop_stream, is_disabled=StreamingState.stream == False, width="100%", color_scheme="red", ), width="100%", ) ) # Add state and page to the app. app = rx.App() app.add_page(index) app.compile() 4. Conclusion So that’s it; in just a few lines of simple code, you’ve created your live streaming graphing web app in pure Python. If you want to learn more about this and how to build graphs with Python check out this . documentation If you have questions, please comment them below or message me on Twitter at or on . Share your app creations on social media and tag me, and I’ll be happy to provide feedback or help retweet! @tgotsman12 LinkedIn Disclaimer: I work as a Founding Engineer at Reflex, where I build the open-source framework.