Intermediate concepts in Python progrmming like:
- Working with files
- The standard library
- Virtual Environments
- Working with modules and packges
- Making API requests
Programs can create data or require data as input during their running time. A very common way to supply data to a running program is via a file. A program may store its intermediate results to a file before post processing and final storage to a storage bucket (S3) or database.
| # Write to a text file | |
| file = open("people-who-owe-me.txt", "w") | |
| file.write("Emmanuel\n") | |
| file.write("Chidera\n") | |
| file.close() |
| # Read from a text file | |
| file = open("people-who-owe-me.txt", "r") | |
| file.seek(0) | |
| content = file.read() | |
| print("People that owe me money:") | |
| print(content) | |
| file.close() |
| # Append to file a text file | |
| filename = "people-who-owe-me.txt" | |
| mode = "a" | |
| # first write operation | |
| file = open(filename, mode) | |
| file.write("Bisola\n") | |
| file.close() | |
| # second write operation | |
| file = open(filename, mode) | |
| file.write("Ganiu\n") | |
| file.close() | |
| # read what has been written so far | |
| file = open(filename, "r") | |
| file.seek(0) | |
| content = file.read() | |
| print("People that owe me money:") | |
| print(content) | |
| file.close() |
| with open("people-who-owe-me.md") as file: | |
| content = file.read() | |
| print(content) | |
| file.write("Ibrahim") | |
| file.write("Mustapha") | |
| print(file.read()) | |
| # no need for close |
| import sqlite3 | |
| import datetime | |
| connection = sqlite3.connect("people_who_owe_me.db") | |
| cursor = connection.cursor() | |
| cursor.execute( | |
| """ | |
| CREATE TABLE IF NOT EXISTS users ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| name TEXT NOT NULL, | |
| address TEXT NOT NULL, | |
| deadline TIMESTAMP | |
| ) | |
| """ | |
| ) | |
| cursor.execute( | |
| """ | |
| INSERT INTO users (name, address, deadline) | |
| VALUES (?, ?, ?) | |
| """, | |
| ( | |
| "Emmanuel", | |
| "No. 5 Orile, Lagos", | |
| datetime.datetime.now() + datetime.timedelta(hours=24) | |
| ) | |
| ) | |
| # connection.commit() | |
| # connection.close() |
| import sqlite3 | |
| import datetime | |
| with sqlite3.connect("people_who_owe_me.db") as connection: | |
| cursor = connection.cursor() | |
| cursor.execute( | |
| """ | |
| CREATE TABLE IF NOT EXISTS users ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| name TEXT NOT NULL, | |
| address TEXT NOT NULL, | |
| deadline TIMESTAMP | |
| ) | |
| """ | |
| ) | |
| cursor.execute(""" | |
| INSERT INTO users (name, address, deadline) | |
| VALUES (?, ?, ?) | |
| """, | |
| ( | |
| "Emmanuel", | |
| "No. 5 Orile, Lagos", | |
| datetime.datetime.now() + datetime.timedelta(hours=24) | |
| ) | |
| ) |
Task: Modify your input collection program from yesterday to write its output to a file
Starting point:
name = input("What is your name: ")
age = int(input("What is your age: "))
interests = ""
for x in range(3):
interest_x = input(f"What is your number {x+1} interest: ")
# if we are at the beginging
if x == 0:
interests += f"{interest_x}"
# if we are the end
elif x == 2:
interests += f", and {interest_x}"
# every other number should have commas in-between
else:
interests += f", {interest_x}"
combined = f"Your name is {name} and you are {age} years old and your interests are {interests}"
print(combined)
# TODO: Write this combined to a file in append mode
# This ensures that new user content gets written at the end
# don't forget to add a new line| name = input("What is your name: ") | |
| age = int(input("What is your age: ")) | |
| interests = "" | |
| for x in range(3): | |
| interest_x = input(f"What is your number {x+1} interest: ") | |
| # if we are at the beginging | |
| if x == 0: | |
| interests += f"{interest_x}" | |
| # if we are the end | |
| elif x == 2: | |
| interests += f", and {interest_x}" | |
| # every other number should have commas in-between | |
| else: | |
| interests += f", {interest_x}" | |
| combined = f"Your name is {name} and you are {age} years old and your interests are {interests}" | |
| print(combined) | |
| # TODO: Write this combined to a file in append mode | |
| # This ensures that new user content gets written at the end | |
| # don't forget to add a new line |
The Python Standard Library allows us to make use of plenty goodies without relying on third parties.
You've already seen:
But it goes beyond to include utilities for making API requests, working with folders, calling native OS utilities (for example, utility for opening an application, like Chrome).
This section shows in greater depth these modules:
| """ | |
| Library path: https://docs.python.org/3/library/datetime.html | |
| Date object: https://docs.python.org/3/library/datetime.html#date-objects | |
| Datetime object: https://docs.python.org/3/library/datetime.html#datetime-objects | |
| """ | |
| import datetime | |
| print("Today is:", datetime.date.today()) | |
| print("The time is: ", datetime.datetime.now().time()) | |
| import os | |
| import time | |
| import datetime | |
| while True: | |
| os.system("cls" if os.name == "nt" else "clear") | |
| print("The time is: ", datetime.datetime.now().time().replace(microsecond=0)) | |
| time.sleep(1) |
| """ | |
| Library docs: https://docs.python.org/3/library/random.html | |
| .random() method: https://docs.python.org/3/library/random.html#random.random | |
| .randint() method: https://docs.python.org/3/library/random.html#random.randint | |
| .randrange() method: https://docs.python.org/3/library/random.html#random.randrange | |
| """ | |
| import random | |
| print("A random number between 0 and 1 is", random.random()) |
| import random | |
| print("Row a dice:", random.randint(1, 6)) | |
| import random | |
| choice = None | |
| while True: | |
| choice = input("Enter a choice of head or tail: ") | |
| if choice.lower() != "head" and choice.lower() != "tail": | |
| print("Please enter either head or tail") | |
| else: | |
| break | |
| random_val_between_0_and_1 = random.random() | |
| if random_val_between_0_and_1 > 0.5: | |
| print("Head wins the toss") | |
| else: | |
| print("Tail wins the toss") | |
| """ | |
| Library docs: https://docs.python.org/3/library/math.html | |
| Sqrt method: https://docs.python.org/3/library/math.html#math.sqrt | |
| """ | |
| import math | |
| print("Square root of 144 is", math.sqrt(144)) | |
| print("Cube root of 27 is", math.cbrt(27)) | |
| print("Cosine of 0 is", math.cos(0)) | |
| print("Sine of 90 (π/2) is", math.sin(0.5 * math.pi)) |
| import tkinter as tk | |
| root = tk.Tk() | |
| root.mainloop() |
| import tkinter as tk | |
| # Create the main window | |
| root = tk.Tk() | |
| root.geometry("400x300") | |
| root.title("Hello Tkinter") | |
| # Create a simple label | |
| label = tk.Label(root, text="Hey guys, I am Tkinter!") # font=("Helvetica", 20, "bold") | |
| label.pack(padx=20, pady=20) | |
| # Run the application | |
| root.mainloop() |
| import tkinter as tk | |
| def show_input(): | |
| user_text = entry.get() | |
| label.config(text=f"You typed: {user_text}") | |
| root = tk.Tk() | |
| root.geometry("400x300") | |
| root.title("Input Example") | |
| large_font = ("Helvetica", 16) | |
| entry = tk.Entry(root, font=large_font) | |
| entry.pack(padx=20, pady=10) | |
| button = tk.Button(root, text="Submit", command=show_input, font=large_font) | |
| button.pack(padx=20, pady=10) | |
| label = tk.Label(root, text="Type something above", font=large_font) | |
| label.pack(padx=20, pady=10) | |
| root.mainloop() |
| import tkinter as tk | |
| def calculate(): | |
| try: | |
| expression = entry.get() | |
| result = eval(expression) | |
| label.config(text=f"Result: {result}") | |
| except Exception: | |
| label.config(text="Error in expression") | |
| root = tk.Tk() | |
| root.title("Basic Calculator") | |
| large_font = ("Helvetica", 16) | |
| entry = tk.Entry(root, width=30, font=large_font) | |
| entry.pack(padx=20, pady=10) | |
| button = tk.Button(root, text="Calculate", command=calculate, font=large_font) | |
| button.pack(padx=20, pady=10) | |
| label = tk.Label(root, text="Enter an expression (e.g., 2+3*4)", font=large_font) | |
| label.pack(padx=20, pady=10) | |
| root.mainloop() |
| import turtle | |
| turtle.forward(100) | |
| turtle.mainloop() |
| import turtle as t | |
| t.forward(100) | |
| t.left(90) | |
| t.forward(100) | |
| t.left(90) | |
| t.forward(100) | |
| t.left(90) | |
| t.forward(100) | |
| t.left(90) | |
| t.exitonclick() |
| import turtle as t | |
| t.width(10) | |
| for i in range(4): | |
| t.forward(100) | |
| t.left(90) | |
| t.exitonclick() |
| import turtle as t | |
| t.width(10) | |
| t.shape("turtle") | |
| t.color("black") # pen color | |
| t.fillcolor("green") # turtle shape fill color | |
| t.penup() | |
| t.goto(0, -200) | |
| t.pendown() | |
| t.circle(200) | |
| t.exitonclick() |
| import antigravity |
| import this |
| # don't forget to import random | |
| # List of famous people with their birth years | |
| famous_people = [ | |
| ("Michael Jackson", 1958), | |
| ("Bola Tinubu", 1952), | |
| ("Nelson Mandela", 1918), | |
| ("Adolf Hitler", 1889) | |
| ] | |
| print("Welcome to the Famous People Birth Year Guessing Game!\n") | |
| # Pick a random person | |
| # Hint use random.choice(famous_people) | |
| # person, birth_year = | |
| # Ask the user to guess the birth year | |
| # guess = int(input(f"When was {person} born? ")) | |
| # Check the guess and let the user know if they are correct or wrong | |
Python allows you to run code that is part of the current environment, or the standard library if no environment is selected.
For example, you can run Python's http server to serve your local file content:
Run this in your command line:
python -m http.serverThen run this:
python -m venv .venv.venv is a folder you created when you ran python -m venv .venv. It could be anything really.
It could be python -m venv env, or python -m venv .virtual_environment. The choice of name and choice of . at the start depends on your team. But it's best to stick to .venv.
Inside this .venv, there are several folders.
$ ls -la .venv
total 8
drwxr-xr-x 5 USER 197121 0 Aug 26 14:00 ./
drwxr-xr-x 3 USER 197121 0 Aug 26 14:00 ../
-rw-r--r-- 1 USER 197121 71 Aug 26 14:00 .gitignore
drwxr-xr-x 2 USER 197121 0 Aug 26 14:00 Include/
drwxr-xr-x 3 USER 197121 0 Aug 26 14:00 Lib/
-rw-r--r-- 1 USER 197121 345 Aug 26 14:00 pyvenv.cfg
drwxr-xr-x 2 USER 197121 0 Aug 26 14:01 Scripts/$ ls -la .venv
drwxr-xr-x 5 osi osi 4096 Aug 26 13:51 .
drwxr-xr-x 3 osi osi 4096 Aug 26 13:51 ..
drwxr-xr-x 2 osi osi 4096 Aug 26 13:51 bin
drwxr-xr-x 3 osi osi 4096 Aug 26 13:51 include
drwxr-xr-x 3 osi osi 4096 Aug 26 13:51 lib
lrwxrwxrwx 1 osi osi 3 Aug 26 13:51 lib64 -> lib
-rw-r--r-- 1 osi osi 179 Aug 26 13:51 pyvenv.cfgThe most important is the Scripts directory (on Windows). Or the bin directory on Unix (Linux/MacOS).
They contain similar content:
drwxr-xr-x 2 osi osi 4096 Aug 26 14:01 .
drwxr-xr-x 5 osi osi 4096 Aug 26 14:00 ..
-rw-r--r-- 1 osi osi 2246 Aug 26 14:01 activate
-rw-r--r-- 1 osi osi 1041 Aug 26 14:01 activate.bat
-rw-r--r-- 1 osi osi 2300 Aug 26 14:01 activate.fish
-rw-r--r-- 1 osi osi 29221 Dec 3 2024 Activate.ps1
-rw-r--r-- 1 osi osi 393 Dec 3 2024 deactivate.bat
-rw-r--r-- 1 osi osi 108439 Aug 26 14:01 pip3.13.exe
-rw-r--r-- 1 osi osi 108439 Aug 26 14:01 pip3.exe
-rw-r--r-- 1 osi osi 108439 Aug 26 14:01 pip.exe
-rw-r--r-- 1 osi osi 254832 Dec 3 2024 python.exe
-rw-r--r-- 1 osi osi 250360 Dec 3 2024 pythonw.exedrwxr-xr-x 2 osi osi 4096 Aug 26 13:51 .
drwxr-xr-x 5 osi osi 4096 Aug 26 13:51 ..
-rw-r--r-- 1 osi osi 2011 Aug 26 13:51 activate
-rw-r--r-- 1 osi osi 937 Aug 26 13:51 activate.csh
-rw-r--r-- 1 osi osi 2213 Aug 26 13:51 activate.fish
-rw-r--r-- 1 osi osi 9033 Aug 26 13:51 Activate.ps1
-rwxr-xr-x 1 osi osi 269 Aug 26 13:51 normalizer
-rwxr-xr-x 1 osi osi 257 Aug 26 13:51 pip
-rwxr-xr-x 1 osi osi 257 Aug 26 13:51 pip3
-rwxr-xr-x 1 osi osi 257 Aug 26 13:51 pip3.11
lrwxrwxrwx 1 osi osi 7 Aug 26 13:51 python -> python3
lrwxrwxrwx 1 osi osi 16 Aug 26 13:51 python3 -> /usr/bin/python3
lrwxrwxrwx 1 osi osi 7 Aug 26 13:51 python3.11 -> python3After creating and sourcing a virtual environment, the next best thing is to install dependencies and manage them
So to install the popular requests module, you run:
pip install requestsThen use it in a python file to make an API request
import requests
response = requests.get("https://jsonplaceholder.typicode.com/users/1")
print(response.text)
# Expected response
"""
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "[email protected]",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
"""You can see the content of your virtual environment by running pip freeze. If you installed requests in a new virtual environment, it comes with 4 other modules (certifi, charset-normalizer, idna, urllib3).
(.venv) osi@system:~/codes$ pip freeze
certifi==2025.8.3
charset-normalizer==3.4.3
idna==3.10
requests==2.32.5
urllib3==2.5.0You should save this output to a file called requirements.txt (it's conventional). This file can then be used by other collaborators to update their environments.
To save it to a file, you can use the unix redirection operator (>):
(.venv) osi@system:~/codes$ pip freeze > requirements.txtOpening up the requirements.txt file will show the same dependencies.
A collaborator can then run:
pip install -r requirements.txtto install the depdencies in that env.
pip freezepip freeze to a file called requirements.txtannotated-types==0.7.0
pydantic==2.11.7
pydantic_core==2.33.2
typing-inspection==0.4.1
typing_extensions==4.15.0
You do not need to write all your code in one single file. Python allows you to split your code into multiple files.
All the standard library modules you've imported so far are actual python files written by the Python maintainers.
You can write your own python files that can be imported, though they might not be added to the standard library, 🥲
| from bank import deposit, withdraw | |
| deposit(400) | |
| withdraw(200) | |
| from fraud_utils.detection import detect_fraud | |
| detect_fraud(3000000000) |
| from bank import deposit | |
| deposit(384) |
You will be grouped into teams to do this exercise
hr_applicationappraisal
utils.py
staff.py
management.py
input_flows.py
main.py
Note that appraisal is a directory.
"employees" = {
"staff": {
"stf01": {
"name": "Ogoni Marthia",
"email": "[email protected]",
"staffId": "stf01"
},
"stf02": {
"name": "Lina Adeyemi",
"email": "[email protected]",
"staffId": "stf02"
},
"stf03": {
"name": "Tunde Bakare",
"email": "[email protected]",
"staffId": "stf03"
}
},
"management": {
"mgmt01": {
"name": "Carol Danvers",
"email": "[email protected]",
"staffId": "mgmt01"
},
"mgmt02": {
"name": "Anayakoji Kafka",
"email": "[email protected]",
"staffId": "mgmt02"
}
}
}appraisal package.input_flows using absolute imports.appraise_staff or appraise_management) for the selected user.input_flows) and relative imports within a package.| import requests | |
| print(requests.get("http://localhost:5000/users").json()) |
| import requests | |
| from bs4 import BeautifulSoup | |
| html = "<html><body><h1>Hello!</h1></body></html>" | |
| soup = BeautifulSoup(html, "html.parser") | |
| print(soup.h1.text) |
| from pydantic import BaseModel | |
| class User(BaseModel): | |
| name: str | |
| email: str | |
| interest1: str | |
| interest2: str | |
| interest3: str | |
| u = User( | |
| name="Ada", | |
| email="[email protected]", | |
| interest1="Music", | |
| interest2="Cooking", | |
| interest3="Chess" | |
| ) | |
| print(u) |
| import requests | |
| BASE_URL = "http://localhost:5000" | |
| resp = requests.get(f"{BASE_URL}/users") | |
| print("Users:", resp.json()) |
| # CLASS EXERCISE: | |
| # Write a client for the Flask API | |
| # 1. Seed users | |
| # 2. Print them | |
| # 3. Add a new user | |
| # 4. Delete a user by ID | |
| import requests | |
| BASE_URL = "http://localhost:5000" |
| from flask import Flask, request, jsonify | |
| import sqlite3 | |
| app = Flask(__name__) | |
| DB_NAME = "class.db" | |
| def init_db(): | |
| with sqlite3.connect(DB_NAME) as conn: | |
| cur = conn.cursor() | |
| cur.execute( | |
| """ | |
| CREATE TABLE IF NOT EXISTS users ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| name TEXT NOT NULL, | |
| email TEXT NOT NULL, | |
| interest1 TEXT NOT NULL, | |
| interest2 TEXT NOT NULL, | |
| interest3 TEXT NOT NULL | |
| ) | |
| """ | |
| ) | |
| conn.commit() | |
| def query_db(query, args=(), one=False): | |
| with sqlite3.connect(DB_NAME) as conn: | |
| conn.row_factory = sqlite3.Row | |
| cur = conn.cursor() | |
| cur.execute(query, args) | |
| rv = cur.fetchall() | |
| conn.commit() | |
| return (rv[0] if rv else None) if one else rv | |
| @app.get("/") | |
| def root_route(): | |
| return "<h1>Hey guys</h1>" | |
| @app.route("/seed", methods=["POST", "GET"]) | |
| def seed(): | |
| users = [ | |
| ("Ada", "[email protected]", "Music", "Cooking", "Chess"), | |
| ("Musa", "[email protected]", "Football", "Traveling", "Movies"), | |
| ("Tomi", "[email protected]", "Reading", "Gaming", "Art"), | |
| ] | |
| query_db("DELETE FROM users") | |
| with sqlite3.connect(DB_NAME) as conn: | |
| cur = conn.cursor() | |
| cur.executemany( | |
| "INSERT INTO users (name, email, interest1, interest2, interest3) VALUES (?, ?, ?, ?, ?)", | |
| users, | |
| ) | |
| conn.commit() | |
| return jsonify({"message": "Users seeded!", "users": get_all_users()}) | |
| def get_all_users(): | |
| rows = query_db("SELECT * FROM users") | |
| return [dict(row) for row in rows] | |
| @app.route("/users", methods=["GET"]) | |
| def get_users(): | |
| return jsonify(get_all_users()) | |
| @app.route("/users", methods=["POST"]) | |
| def add_user(): | |
| data = request.get_json() | |
| required = {"name", "email", "interest1", "interest2", "interest3"} | |
| if not data or not required.issubset(data): | |
| return jsonify({"error": "Missing one of: name, email, interest1-3"}), 400 | |
| query_db( | |
| "INSERT INTO users (name, email, interest1, interest2, interest3) VALUES (?, ?, ?, ?, ?)", | |
| (data["name"], data["email"], data["interest1"], data["interest2"], data["interest3"]), | |
| ) | |
| return jsonify({"message": "User added", "users": get_all_users()}), 201 | |
| @app.route("/users/<int:user_id>", methods=["DELETE"]) | |
| def delete_user(user_id): | |
| query_db("DELETE FROM users WHERE id = ?", (user_id,)) | |
| return jsonify({"message": f"User {user_id} deleted", "users": get_all_users()}) | |
| if __name__ == "__main__": | |
| init_db() | |
| app.run(debug=True) |
| def deposit(amount: int): | |
| print(f"{amount} deposited successfully") | |
| def withdraw(amount: int): | |
| print(f"{amount} withdrawn successfully") | |
| def transfer(amount: int): | |
| print(f"{amount} transfered successfully") | |
| # from banking_security_utils.hashing.sha256 import hash_data | |
| # hash_data("my-sweet-sweet-password") |