Week 07: Working with external data
with open() context managerwith?: Automatically closes the file even if errors occur"r" (read), "w" (write/overwrite), "a" (append)with so the file closes reliably when the block exits# Saving a contact list to a text file - messy!
with open("contacts.txt", "w") as f:
f.write("Alice|alice@example.com|555-1234\n")
f.write("Bob|bob@example.com|555-5678\n")
# Reading it back - lots of manual parsing
with open("contacts.txt", "r") as f:
for line in f:
parts = line.strip().split("|")
name, email, phone = parts
print(f"{name}: {email}")|), fragile parsing, no nested data, no type info|? What about optional fields? Nested addresses?| JSON Type | Python Type | Example |
|---|---|---|
Object {} |
Dictionary | {"name": "Alice", "age": 30} |
Array [] |
List | [1, 2, 3, 4, 5] |
| String | String | "hello" |
| Number | int/float | 42, 3.14 |
| Boolean | Boolean | true → True, false → False |
| Null | None | null → None |
json librarydump() and load()import json
# Python dictionary (complex, nested structure)
contacts = {
"people": [{"name": "Alice", "email": "alice@example.com", "age": 30},
{"name": "Bob", "email": "bob@example.com", "age": 25}
],
"count": 2
}
# Write Python object to JSON file
with open("contacts.json", "w") as f:
json.dump(contacts, f, indent=4) # indent=4 makes it readable
# Read JSON file back into Python object
with open("contacts.json", "r") as f:
data = json.load(f)
print(data["people"][0]["name"]) # Output: Alicejson.dump(obj, file): Python object → JSON filejson.load(file): JSON file → Python objectindent=4: Makes JSON human-readable (use in development, skip in production)https://api.github.com/users/octocat/repos
└─┬─┘ └────────┬─────────┘ └─────┬────────┘
│ base URL endpoint path
protocol
https://api.github.com - the server you’re talking to/users/octocat/repos - the specific resource you wantGET (retrieve data), POST (send data), PUT (update), DELETE (remove)GET requests to retrieve datarequests libraryjson, we need to install requestsurllib.request; urllib3 is a separate third-party packageimport requests
# Make a GET request to the PokeAPI
url = "https://pokeapi.co/api/v2/pokemon/pikachu"
response = requests.get(url, timeout=10)
# Check if the request was successful
if response.status_code == 200:
# Parse the JSON response into a Python dictionary
data = response.json()
print(f"Name: {data['name'].title()}")
print(f"Height: {data['height']} decimetres")
print(f"Weight: {data['weight']} hectograms")
else:
print(f"Error: Received status code {response.status_code}")requests.get(url): Makes HTTP GET request, returns response objectresponse.status_code: HTTP status code (200 = success)response.json(): Parses JSON response → Python dict (same as json.load()!)| Code | Meaning | Example |
|---|---|---|
| 200 | OK - Success | Data retrieved successfully |
| 201 | Created | New resource created |
| 400 | Bad Request | Invalid data sent |
| 401 | Unauthorized | Need authentication |
| 404 | Not Found | Resource doesn’t exist |
| 500 | Server Error | Something broke on server |
raise_for_status() before processing dataReading JSON from a file:
import requests
url = "https://api.example.com/data"
try:
response = requests.get(url, timeout=5) # 5 second timeout
response.raise_for_status() # Raises exception for 4xx/5xx codes
data = response.json()
print(f"Success: {data}")
except requests.exceptions.Timeout:
print("Error: Request timed out")
except requests.exceptions.ConnectionError:
print("Error: Could not connect to server")
except requests.exceptions.HTTPError as e:
print(f"Error: HTTP {e.response.status_code}")
except requests.exceptions.JSONDecodeError:
print("Error: Response was not valid JSON")timeout= parameter (seconds)raise_for_status(): Converts error codes into exceptions.env files, never commit to git)import json
import requests
# 1. Fetch live data from API
response = requests.get(
"https://pokeapi.co/api/v2/pokemon/ditto",
timeout=10,
)
response.raise_for_status()
pokemon_data = response.json()
# 2. Process the data (extract what we need)
simplified = {
"name": pokemon_data["name"],
"height": pokemon_data["height"],
"weight": pokemon_data["weight"],
"types": [t["type"]["name"] for t in pokemon_data["types"]]
}
# 3. Save to local JSON file for offline use
with open("pokemon_cache.json", "w") as f:
json.dump(simplified, f, indent=4)
print("Data fetched from API and saved locally!")lab07_contact_book.py: Implement save_contacts_to_json and load_contacts_from_jsonindent=4; return an empty list when the file is missinglab07_api_client.py: Implement get_api_data(url)requests.get(url, timeout=10), raise_for_status(), and response.json()None for request failures or invalid JSONjson.load() (files) and response.json() (APIs) both give you Python dictsNext steps: - Review Lab 07 instructions in week07/lab07.md - Implement the two specified modules - Run the offline tests before pushing
Office hours: Bring the failing test, traceback, and current diff.
IS 4010: App Dev with AI