Quiz: Working with Data: CSV, JSON, and APIs

Test your understanding before moving on. Target: 70% or higher to proceed confidently.


Section 1: Multiple Choice (1 point each)

1. What argument should you always pass when opening a CSV file in Python to prevent extra blank lines on some platforms?

  • A) encoding="utf-8"
  • B) newline=""
  • C) mode="csv"
  • D) buffering=0
Answer **B)** `newline=""` *Why B:* The `csv` module handles its own newline translation. Passing `newline=""` prevents the OS from adding extra line endings, which causes blank rows on Windows. *Why not A:* Encoding is important but doesn't solve the blank line problem. *Why not C:* There is no `"csv"` mode for `open()`. *Why not D:* Buffering controls write behavior, not newline handling. *Reference:* Section 21.2.1

2. What is the main advantage of csv.DictReader over csv.reader?

  • A) It's faster for large files
  • B) It reads columns by name instead of by index
  • C) It automatically converts data types
  • D) It supports writing as well as reading
Answer **B)** It reads columns by name instead of by index *Why B:* `DictReader` maps each row to a dictionary keyed by column headers, so you write `row["name"]` instead of `row[0]`. This is more readable and resilient to column reordering. *Why not A:* `DictReader` is actually slightly slower due to dict creation overhead. *Why not C:* All CSV values are still strings — you must convert types manually. *Why not D:* `DictReader` is read-only; `DictWriter` handles writing. *Reference:* Section 21.2.2

3. How does the CSV standard handle a field that contains a comma?

  • A) It replaces the comma with a semicolon
  • B) It escapes the comma with a backslash
  • C) It wraps the field in double quotes
  • D) It splits the field into two columns
Answer **C)** It wraps the field in double quotes *Why C:* Per RFC 4180, fields containing commas, newlines, or double quotes are enclosed in double quotes. The `csv` module handles this automatically. *Why not A:* The data is preserved exactly; no characters are replaced. *Why not B:* CSV uses quoting, not backslash escaping. *Why not D:* That would corrupt the data — the whole point is to keep it as one field. *Reference:* Section 21.2.3

4. What does the s in json.loads() and json.dumps() stand for?

  • A) "safe" — these are the safe versions
  • B) "string" — they work with strings instead of files
  • C) "standard" — they follow the JSON standard
  • D) "serialize" — they handle serialization
Answer **B)** "string" — they work with strings instead of files *Why B:* `json.load()` reads from a file object; `json.loads()` parses a string. `json.dump()` writes to a file object; `json.dumps()` produces a string. The `s` suffix distinguishes the string versions. *Reference:* Section 21.3.1

5. What happens when you serialize a Python tuple to JSON and then parse it back?

  • A) It remains a tuple
  • B) It becomes a list
  • C) It becomes a string
  • D) It raises a TypeError
Answer **B)** It becomes a list *Why B:* JSON has no tuple type — Python tuples are serialized as JSON arrays, which are deserialized back as Python lists. The distinction between tuples and lists is lost in the round trip. *Reference:* Section 21.3.4

6. In the restaurant analogy for APIs, what does the "menu" represent?

  • A) The HTTP protocol
  • B) The API documentation
  • C) The server's database
  • D) The response data
Answer **B)** The API documentation *Why B:* The menu tells you what you can order (what endpoints are available and what parameters they accept). Similarly, API documentation describes available endpoints, request formats, and response structures. *Reference:* Section 21.4.1

7. Which HTTP method is used to retrieve data from an API?

  • A) POST
  • B) PUT
  • C) GET
  • D) DELETE
Answer **C)** GET *Why C:* GET requests ask the server to return data. POST sends data for processing/creation, PUT updates existing data, and DELETE removes data. *Reference:* Section 21.4.2

8. What does HTTP status code 429 mean?

  • A) Resource not found
  • B) Internal server error
  • C) Unauthorized access
  • D) Too many requests (rate limited)
Answer **D)** Too many requests (rate limited) *Why D:* 429 means you've exceeded the API's rate limit. The correct response is to wait (ideally using exponential backoff) before retrying. *Why not A:* That's 404. *Why not B:* That's 500. *Why not C:* That's 401. *Reference:* Section 21.5.4

9. What is the recommended way to pass query parameters in a requests.get() call?

  • A) Append them directly to the URL string
  • B) Use the params dictionary argument
  • C) Put them in the request body
  • D) Use the headers argument
Answer **B)** Use the `params` dictionary argument *Why B:* The `params` dict is cleaner, less error-prone, and automatically handles URL encoding of special characters like spaces and Unicode. *Why not A:* Manual URL construction is fragile and doesn't handle encoding. *Why not C:* Query parameters go in the URL, not the body (which is for POST data). *Why not D:* Headers carry metadata, not query parameters. *Reference:* Section 21.5.5

10. What does response.json() do?

  • A) Checks if the response is valid JSON
  • B) Converts the response to a JSON file
  • C) Parses the response body as JSON and returns a Python object
  • D) Sets the response content type to JSON
Answer **C)** Parses the response body as JSON and returns a Python object *Why C:* `response.json()` is equivalent to `json.loads(response.text)`. It parses the JSON text in the response body and returns the corresponding Python dict or list. *Reference:* Section 21.5.3

Section 2: Short Answer (2 points each)

11. You receive a CSV file where some address fields contain commas (like "123 Main St, Suite 4"). Explain why line.split(",") will produce incorrect results and what you should use instead.

Answer `line.split(",")` treats every comma as a field separator, so `"123 Main St, Suite 4"` would be split into two separate fields: `"123 Main St"` and `" Suite 4"`. The `csv` module should be used instead because it understands quoting rules — it recognizes that commas inside quoted fields are part of the data, not delimiters. (Section 21.2.3)

12. When would you choose CSV over JSON for storing data, and when would you choose JSON over CSV? Give one specific scenario for each.

Answer **CSV is better** for flat, tabular data where every record has the same fields — for example, a spreadsheet of employee records with name, department, hours, and rate. CSV is smaller, opens directly in Excel/Google Sheets, and is the standard import format for most analytics tools. **JSON is better** for hierarchical or variable-structure data — for example, API responses where a user record contains a nested address object and a variable-length list of posts. JSON preserves data types (numbers, booleans, null) and supports nesting naturally. (Section 21.3.5)

13. What is "exponential backoff" and why is it used when handling rate-limited API responses?

Answer Exponential backoff means waiting progressively longer between retry attempts — for example, 1 second, then 2 seconds, then 4 seconds. It's used when an API returns a 429 (rate limited) response. The increasing delays give the server time to recover and reduce the load from retrying clients. Without backoff, rapid retries would just trigger more rate limiting. (Section 21.7.2)

14. Explain the defensive .get() chain pattern: data.get("address", {}).get("city", "Unknown"). Why use this instead of data["address"]["city"]?

Answer The `.get()` chain provides safe navigation through nested dictionaries. If the `"address"` key is missing, `data.get("address", {})` returns an empty dict instead of raising a `KeyError`. The subsequent `.get("city", "Unknown")` then returns `"Unknown"` because the empty dict has no `"city"` key. With `data["address"]["city"]`, a missing `"address"` key would crash the program with a `KeyError`. This pattern is essential when working with API responses that may have optional or missing fields. (Section 21.6.3)

Section 3: Code Analysis (2 points each)

15. What is wrong with the following code? Identify the bug and explain how to fix it.

import csv

with open("data.csv", "w") as f:
    writer = csv.writer(f)
    writer.writerow(["name", "score"])
    writer.writerow(["Alice", 95])
    writer.writerow(["Bob", 88])
Answer The `open()` call is missing `newline=""`. On Windows, this can result in extra blank lines between rows in the output file. The fix:
with open("data.csv", "w", newline="") as f:
This is a platform-specific bug — it may work fine on macOS/Linux but produce incorrect output on Windows. Always include `newline=""` when working with the `csv` module. (Section 21.2.1)

16. What will the following code print? Trace through it carefully.

import json

data = {"name": "Alice", "scores": [92, 88, 95], "active": True}
json_str = json.dumps(data)
parsed = json.loads(json_str)

print(type(json_str))
print(parsed["scores"][1])
print(data == parsed)
print(data is parsed)
Answer
<class 'str'>
88
True
False
- `json.dumps()` returns a string, so `type(json_str)` is ``. - `parsed["scores"][1]` accesses the second element of the scores list: `88`. - `data == parsed` is `True` because the values are identical after the round trip. - `data is parsed` is `False` because `json.loads()` creates a new dict object — they're equal in value but not the same object in memory. (Sections 21.3.1, connects to [Ch 8](../../part-03-data/chapter-08-lists-and-tuples/index.md) identity vs equality)

17. The following code makes an API call but doesn't handle errors well. List three specific failure scenarios that would crash this code, and show how to fix them.

import requests

response = requests.get("https://api.example.com/data")
data = response.json()
result = data["results"][0]["name"]
print(result)
Answer Three failure scenarios: 1. **Network error:** If the connection fails (no internet, DNS failure), `requests.get()` raises `requests.exceptions.ConnectionError`. 2. **Non-JSON response:** If the server returns HTML or an error page, `response.json()` raises `requests.exceptions.JSONDecodeError`. 3. **Missing keys:** If the response JSON doesn't have a `"results"` key, or `"results"` is empty, `data["results"][0]["name"]` raises `KeyError` or `IndexError`. Fixed version:
import requests

try:
    response = requests.get("https://api.example.com/data", timeout=10)
    response.raise_for_status()
    data = response.json()
    results = data.get("results", [])
    if results:
        print(results[0].get("name", "Unknown"))
    else:
        print("No results found.")
except requests.exceptions.RequestException as e:
    print(f"Request failed: {e}")
except ValueError:
    print("Response was not valid JSON.")
(Sections 21.6, 21.7.3)

Section 4: Applied Understanding (3 points each)

18. Describe the five stages of a data pipeline and give a concrete example of what happens at each stage using Elena's nonprofit report scenario (combining donation CSV, program metrics JSON, and location API data).

Answer 1. **Load:** Read donation records from `donations.csv` using `csv.DictReader`, load program metrics from `metrics.json` using `json.load()`, and fetch location data from a geocoding API using `requests.get()`. 2. **Clean:** Convert string amounts to floats (`float(row["amount"])`), handle missing fields with defaults, remove rows with invalid data (e.g., negative donation amounts). 3. **Enrich:** For each donation, look up the donor's zip code in the geocoding API to add city and state information. Merge program metrics with donation categories. 4. **Aggregate:** Calculate totals by city, averages by program, and overall statistics like total donations and donor count. 5. **Output:** Generate a formatted report, write summary data to `report.csv` using `csv.DictWriter`, and save the full enriched dataset to `report.json` using `json.dump()`. (Section 21.8)

19. The chapter describes APIs as "the connective tissue of the internet." In your own words, explain this threshold concept. Give three real-world examples of apps you use daily that rely on APIs, and identify what data each API likely provides.

Answer APIs are "connective tissue" because they allow separate applications and services to communicate and share data, much like connective tissue links organs in a body. No modern app is self-contained — each relies on specialized services that provide specific capabilities via APIs. Three examples (student answers will vary): 1. **Maps app:** Calls a routing API (directions), a traffic API (real-time congestion), a places API (business info), and a geocoding API (address to coordinates). 2. **Social media app:** Calls an authentication API (login), a content delivery API (photos/videos), a notification API (push alerts), and an ads API (targeted advertising). 3. **Ride-sharing app:** Calls a mapping API (route calculation), a payment API (charge the rider), a pricing API (surge pricing), and a communication API (text/call the driver). The key insight is that your Python programs can access these same APIs. Once you know how to make HTTP requests and parse JSON responses, the internet's data and services become available to your programs. (Section 21.4.3)

20. Compare and contrast CSV and JSON using the following criteria: (a) handling of data types, (b) support for nested/hierarchical data, (c) file size for 1000 identical records, (d) human readability, (e) tool support for non-programmers.

Answer | Criterion | CSV | JSON | |-----------|-----|------| | **(a) Data types** | Everything is stored as strings; readers must convert types manually | Preserves strings, numbers, booleans, and null natively | | **(b) Nesting** | Not supported; data must be flat (rows and columns) | Natively supports nested objects and arrays to arbitrary depth | | **(c) File size** | Smaller — column names appear once (header row) | Larger — key names are repeated for every record | | **(d) Human readability** | Easy for small files; hard to read wide tables | Pretty-printed JSON is readable; compact JSON is hard to scan | | **(e) Non-programmer tools** | Excellent — opens in Excel, Google Sheets, Numbers | Limited — requires a JSON viewer or text editor; no native spreadsheet support | (Section 21.3.5)