๐งช Practice: Ecosystem
The full professional workflow, end to end: venv โ packages โ Git โ API call. This is the setup ritual you'll perform for every real project for the rest of your career. Do it with your own hands โ this one's mostly doing, less reading.
Exercise 1 โ The project ritual (do it for real)
Create a project called eco-practice with the complete professional setup:
# 1. Create the folder and enter it
# 2. Create a virtual environment
# 3. Activate it
# 4. Install requests
# 5. Freeze requirements.txt
# 6. Verify: pip list shows requests inside YOUR venvExercise 2 โ The Git layer
Initialize a Git repo in eco-practice, create a .gitignore (exclude .venv/), make your first commit, and confirm git status is clean.
Exercise 3 โ The API call
Inside the project, write main.py that fetches a random useless fact from this free API (no key needed):
API: https://uselessfacts.jsph.pl/api/v2/facts/randomPrint just the fact's text. Handle: network failure, and a missing "text" key.
Exercise 4 โ The retry wrapper
Wrap your API call in a function get_fact(retries=3) that tries up to 3 times before giving up, printing "Attempt X failed" between tries.
Exercise 5 โ Persist the facts
Every fact fetched gets saved to facts.json (a list that grows across runs). Run the script 3 times โ the file should hold 3 facts.
Solutions
Exercise 1 โ the ritual:
mkdir eco-practice
cd eco-practice
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install requests
pip freeze > requirements.txt
pip list # confirm requests is thereExercise 2:
git init
# create .gitignore containing: .venv/
git add .
git commit -m "Initial setup with requests"
git status # cleanExercise 3 โ main.py:
import requests
try:
response = requests.get(
"https://uselessfacts.jsph.pl/api/v2/facts/random",
timeout=10,
)
response.raise_for_status()
data = response.json()
print(data.get("text", "No text available"))
except requests.exceptions.RequestException as err:
print(f"Network problem: {err}")Exercise 4:
import requests
def get_fact(retries=3):
for attempt in range(1, retries + 1):
try:
response = requests.get(
"https://uselessfacts.jsph.pl/api/v2/facts/random",
timeout=10,
)
response.raise_for_status()
return response.json().get("text")
except requests.exceptions.RequestException as err:
print(f"Attempt {attempt} failed: {err}")
return None
fact = get_fact()
print(fact or "All attempts failed")Exercise 5:
import json
import os
FILE = "facts.json"
facts = []
if os.path.exists(FILE):
with open(FILE) as f:
facts = json.load(f)
fact = get_fact() # the function from Exercise 4
if fact:
facts.append(fact)
with open(FILE, "w") as f:
json.dump(facts, f, indent=2)
print(f"{len(facts)} facts collected")โ Module 11 Checkpoint
You just performed the complete professional project setup โ venv, packages, Git, API integration, persistence, retries. This ritual is the same at every company and every hackathon.
Final module: Capstone โ prove the whole course with one build of your own.