Sprint 4 Tech Talk Notes | Flask and Python Web Server Dev Intro | GiCS Panel Notes |
BI 4.1 Internet - Web Server
Quick launch into Flask, sending and receiving data from a web server.
- Introduction
- Our Goals for Today
- Hello, World!
- Hacks
Introduction
Welcome to this journey into the world of web servers and the Flask framework! In the previous weeks, you’ve successfully set up a web server using GitHub Pages, converting Jupyter Notebooks into Markdown for a seamless online presentation. Today, we’ll take that knowledge to the next level as we dive into creating your very own web server using Flask.
Understanding Web Servers
What is a Web Server?
Traditionally, we had librarians at libraries that would help you find books or information. Today in the digital world, thousands upon thousands of home pages, search engines, and digital archives have been built using web servers.
GitHub Pages vs. Flask
You’ve already experienced a form of web server through GitHub Pages. Think of GitHub Pages as a library that has established rules for publishing Markdown notes and Jupyter Notebooks neatly on a bookshelf.
Now, let’s introduce Flask, your personal web server. Flask can create and manage any type of content, including customizing everything according to your preferences, and even serve additional information (like a database with APIs).
The Flask Framework Flask is a micro web framework written in Python. It’s designed to be minimal and easy to use, making it perfect for building web applications, APIs, and, yes, even your web server. Today, we will start with the basics of Flask and see how it empowers you to create and manage web content.
Our Goals for Today
Here’s what we’ll accomplish in this session:
- Create a minimal Flask server.
- Explore the Python/Flask process.
- Access data from our Flask server using Python.
- Access data from our Flask server using JavaScript.
- Learn how to stop the Python/Flask process gracefully.
Install required libraries
These libraries are required to run and interact with the Python web server.
!pip install flask flask-cors requests
Collecting flask
Downloading flask-3.1.0-py3-none-any.whl.metadata (2.7 kB)
Collecting flask-cors
Using cached Flask_Cors-5.0.0-py2.py3-none-any.whl.metadata (5.5 kB)
Requirement already satisfied: requests in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (2.32.3)
Collecting Werkzeug>=3.1 (from flask)
Downloading werkzeug-3.1.3-py3-none-any.whl.metadata (3.7 kB)
Requirement already satisfied: Jinja2>=3.1.2 in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (from flask) (3.1.4)
Collecting itsdangerous>=2.2 (from flask)
Using cached itsdangerous-2.2.0-py3-none-any.whl.metadata (1.9 kB)
Collecting click>=8.1.3 (from flask)
Using cached click-8.1.7-py3-none-any.whl.metadata (3.0 kB)
Collecting blinker>=1.9 (from flask)
Downloading blinker-1.9.0-py3-none-any.whl.metadata (1.6 kB)
Requirement already satisfied: charset-normalizer<4,>=2 in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (from requests) (3.4.0)
Requirement already satisfied: idna<4,>=2.5 in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (from requests) (3.10)
Requirement already satisfied: urllib3<3,>=1.21.1 in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (from requests) (2.2.3)
Requirement already satisfied: certifi>=2017.4.17 in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (from requests) (2024.8.30)
Requirement already satisfied: MarkupSafe>=2.0 in /home/rguha/nighthawk/risha_guha_2025_1/venv/lib/python3.12/site-packages (from Jinja2>=3.1.2->flask) (3.0.1)
Downloading flask-3.1.0-py3-none-any.whl (102 kB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m103.0/103.0 kB[0m [31m1.5 MB/s[0m eta [36m0:00:00[0m00:01[0m
[?25hUsing cached Flask_Cors-5.0.0-py2.py3-none-any.whl (14 kB)
Downloading blinker-1.9.0-py3-none-any.whl (8.5 kB)
Using cached click-8.1.7-py3-none-any.whl (97 kB)
Using cached itsdangerous-2.2.0-py3-none-any.whl (16 kB)
Downloading werkzeug-3.1.3-py3-none-any.whl (224 kB)
[2K [90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━[0m [32m224.5/224.5 kB[0m [31m2.9 MB/s[0m eta [36m0:00:00[0ma [36m0:00:01[0m
[?25hInstalling collected packages: Werkzeug, itsdangerous, click, blinker, flask, flask-cors
Successfully installed Werkzeug-3.1.3 blinker-1.9.0 click-8.1.7 flask-3.1.0 flask-cors-5.0.0 itsdangerous-2.2.0
Start Web Server
This Python code provides a simple server with an accessible API.
Note: Jupyter magic commmand %%python --bg
that follows runs the server in background. This enables us to continue interacting with the subsequent Notebook cells.
%%python --bg
from flask import Flask, jsonify
from flask_cors import CORS
# initialize a flask application (app)
app = Flask(__name__)
CORS(app, supports_credentials=True, origins='*') # Allow all origins (*)
# ... your existing Flask
# add an api endpoint to flask app
@app.route('/api/data')
def get_data():
# start a list, to be used like a information database
InfoDb = []
# add a row to list, an Info record
InfoDb.append({
"FirstName": "John",
"LastName": "Mortensen",
"DOB": "October 21",
"Residence": "San Diego",
"Email": "jmortensen@powayusd.com",
"Owns_Cars": ["2015-Fusion", "2011-Ranger", "2003-Excursion", "1997-F350", "1969-Cadillac"]
})
# add a row to list, an Info record
InfoDb.append({
"FirstName": "Risha",
"LastName": "Guha",
"DOB": "October 22",
"Residence": "San Diego",
"Email": "rishag22742@stu.powayusd.com",
"Owns_Cars": ["None"]
})
return jsonify(InfoDb)
# add an HTML endpoint to flask app
@app.route('/')
def say_hello():
html_content = """
<html>
<head>
<title>Hellox</title>
</head>
<body>
<h2>Hello, World!</h2>
</body>
</html>
"""
return html_content
if __name__ == '__main__':
# starts flask server on default port, http://127.0.0.1:5001
app.run(port=5001)
Explore the Python/Flask process with Linux
This script discovers the running flask process on your machine using Linux commands.
- lsof - list open files
lsof
andawk
return the process id, sops
can list details, the vericle bar is called apipe
. A pipe flows output from one command to the next.curl
is a Linux utiltity that is easiest way to test if web server is responding
%%script bash
# After app.run(), see the the Python open files on port 5001
echo "Python open files on port 5001"
lsof -i :5001
# see the the Python process
echo
echo "Python process"
lsof -i :5001 | awk '/Python/ {print $2}' | xargs ps
# show ontent of the Python server using curl
echo
echo "Content of the Python root endpoint (aka /), using curl",
curl http://localhost:5001/
Python open files on port 5001
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python 1255539 rguha 3u IPv4 22203657 0t0 TCP localhost:5001 (LISTEN)
Python process
your 131072x1 screen size is bogus. expect trouble
PID TTY TIME CMD
401 pts/0 00:00:00 sh
402 pts/0 00:00:00 sh
407 pts/0 00:00:00 sh
411 pts/0 00:16:00 node
1608 pts/0 00:16:11 node
934453 pts/0 00:00:31 node
934467 pts/0 00:42:48 node
934515 pts/0 00:00:09 node
934592 pts/0 00:00:04 pet
935858 pts/0 00:00:07 node
935958 pts/0 00:00:18 node
936290 pts/0 00:00:18 node
1051569 pts/0 00:00:18 node
1051580 pts/0 00:26:53 node
1051667 pts/0 00:00:01 pet
1052758 pts/0 00:00:04 node
1055117 pts/0 00:00:03 node
1055123 pts/0 00:00:03 node
1055153 pts/0 00:00:03 node
1056140 pts/0 00:02:27 node
1057025 pts/0 00:00:00 sqlite3-editor-
1242964 pts/0 00:00:12 node
1242975 pts/0 00:02:46 node
1243088 pts/0 00:00:06 node
1243139 pts/0 00:00:04 pet
1244420 pts/0 00:00:07 node
1244485 pts/0 00:00:00 node
1244625 pts/0 00:00:33 node
1248721 pts/0 00:01:18 node
1248732 pts/0 00:00:02 node
1248775 pts/0 00:00:03 node
1248848 pts/0 00:00:00 pet
1249082 pts/0 00:00:21 node
1249093 pts/0 00:00:00 node
1251483 pts/0 00:00:03 python
1255539 pts/0 00:00:00 python
1259691 pts/0 00:00:00 bash
1259692 pts/0 00:00:00 bash
1259694 pts/0 00:00:00 awk
1261081 pts/0 00:00:00 bash
1261085 pts/0 00:00:00 xargs
1261086 pts/0 00:00:00 ps
Content of the Python root endpoint (aka /), using curl,
<html>
<head>
<title>Hellox</title>
</head>
<body>
<h2>Hello, World!</h2>
</body>
</html>
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 135 100 135 0 0 29980 0 --:--:-- --:--:-- --:--:-- 33750
Access data from our Flask server using Python
The code block below shows alternate ways to access the Web Server.
- Import requests and use it to obtain response from endpoints
- The response is a Python object that contains status codes and data
- The data can be in different forms, we will be focussed on JSON responses in Full-Stack.
import requests
from IPython.display import HTML, display
# call api root endpoint (aka '/'), often called home page
response = requests.get('http://127.0.0.1:5001/')
# output response in different forms
print("Print Status Message:", response)
print("\nPrint Raw HTML:\n", response.text)
display(HTML(response.text))
# call unknown api endpoint
response = requests.get('http://127.0.0.1:5001/unknown-page')
print("Print Status Message:", response)
response = requests.get('http://127.0.0.1:5001/')
print("Print Status Message:", response)
Print Status Message: <Response [200]>
Print Raw HTML:
<html>
<head>
<title>Hellox</title>
</head>
<body>
<h2>Hello, World!</h2>
</body>
</html>
Hello, World!
Print Status Message: <Response [404]>
Print Status Message: <Response [200]>
import requests
# an api endpoint most commonly returns JSON data
response = requests.get('http://127.0.0.1:5001/api/data')
response.json()
[{'DOB': 'October 21',
'Email': 'jmortensen@powayusd.com',
'FirstName': 'John',
'LastName': 'Mortensen',
'Owns_Cars': ['2015-Fusion',
'2011-Ranger',
'2003-Excursion',
'1997-F350',
'1969-Cadillac'],
'Residence': 'San Diego'},
{'DOB': 'October 22',
'Email': 'rishag22742@stu.powayusd.com',
'FirstName': 'Risha',
'LastName': 'Guha',
'Owns_Cars': ['None'],
'Residence': 'San Diego'}]
Access data from our Flask server using JavaScript
This sample is very similar to Full-Stack as the JavaScript is running through Jupyter and the Web server is a Python Process running on our machine (local server).
- HTML is used to setup basics of a table
- The script block, has javascript fetch that passes endpoint (url) and options. The options are critical to communicating request requirements.
- Similar to python examples, data is extracted and that data is written to the document, which is what is viewable to the user as the page is rendered. Headings are static in the document, but rows are dynamically extracted according to the information contained in the server.
%%html
<h1>Access data from our Flask server using JavaScript</h1>
<p>This code extracts data "live" from a local Web Server with JavaScript fetch. Additionally, it formats the data into a table.</p>
<!-- Head contains information to Support the Document -->
<!-- HTML table fragment for page -->
<table id="demo" class="table">
<thead>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Residence</th>
</tr>
</thead>
<tbody id="result">
<!-- javascript generated data -->
</tbody>
</table>
<script>
function dataLocalStoreAndDisplay() {
// prepare HTML result container for new output
let resultContainer = document.getElementById("result");
// prepare URL
url = "http://127.0.0.1:5001/api/data";
// set options for cross-origin header request
let options = {
method: 'GET', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'default', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'include', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json',
},
};
// fetch the API
fetch(url, options)
// response is a RESTful "promise" on any successful fetch
.then(response => {
// check for response errors and display
if (response.status !== 200) {
console.error(response.status);
return;
}
// valid response will contain JSON data
response.json().then(data => {
console.log(data);
for (const row of data) {
// tr and td build out for each row
const tr = document.createElement("tr");
const firstname = document.createElement("td");
const lastname = document.createElement("td");
const residence = document.createElement("td");
// data is specific to the API
firstname.innerHTML = row.FirstName;
lastname.innerHTML = row.LastName;
residence.innerHTML = row.Residence;
// this builds each td into tr
tr.appendChild(firstname);
tr.appendChild(lastname);
tr.appendChild(residence);
// add HTML to container
resultContainer.appendChild(tr);
}
});
})
.catch(error => console.error("Fetch error:", error));
}
dataLocalStoreAndDisplay();
</script>
Access data from our Flask server using JavaScript
This code extracts data "live" from a local Web Server with JavaScript fetch. Additionally, it formats the data into a table.
First Name | Last Name | Residence |
---|
Stop the Python/Flask process
This script ends Python/Flask process using pipes to obtain the python process. Then echo the python process to kill -9
.
%%script bash
python_ps=$(sudo lsof -i :5001 | awk '/python/ {print $2}')
echo "Killing python process with PID: $python_ps"
echo $python_ps | sudo kill -9
Hacks
Edit, stop and start the web server.
- Add to the Home Page
- Add your own information to the Web API
- Use from Template to start your own Team Flask project https://github.com/nighthawkcoders/flocker_backend