Module 03 / Project 04 — Error Handling¶
Learn Your Way¶
| Read | Build | Watch | Test | Review | Visualize | Try |
|---|---|---|---|---|---|---|
| — | This project | — | — | Flashcards | — | — |
Focus¶
- Checking HTTP status codes and using
raise_for_status() - Handling connection errors, timeouts, and HTTP errors
- Implementing retries with exponential backoff
- Writing defensive code for unreliable networks
Why this project exists¶
APIs fail. Networks drop. Servers return errors. If your code does not handle these cases, it crashes with an unhelpful traceback. This project teaches you how to make your API calls resilient by catching specific errors, retrying failed requests, and giving users clear feedback about what went wrong.
Run¶
Expected output¶
--- Test 1: Successful request ---
Status: 200 OK
Title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
--- Test 2: 404 Not Found ---
HTTP error: 404 Client Error: Not Found for url: https://jsonplaceholder.typicode.com/posts/99999
--- Test 3: Connection error (bad domain) ---
Connection error: could not reach https://not-a-real-domain-xyz.com/posts/1
--- Test 4: Timeout (very short limit) ---
Timeout: request to https://jsonplaceholder.typicode.com/posts took longer than 0.001s
--- Test 5: Retry with backoff ---
Attempt 1 of 3: requesting https://jsonplaceholder.typicode.com/posts/1
Success on attempt 1.
Title: sunt aut facere repellat provident occaecati excepturi optio reprehenderit
Alter it¶
- Change the retry function to attempt 5 times instead of 3. Increase the base delay to 2 seconds.
- Add a test that uses
response.status_codeto check for a 200 before parsing JSON, without usingraise_for_status(). - Add a test that catches
requests.exceptions.JSONDecodeErrorby requesting a URL that returns non-JSON content (tryhttps://jsonplaceholder.typicode.com/— the homepage returns HTML).
Break it¶
- Set the timeout to
0(not0.001, literally0). What error do you get? Is it a timeout error or something else? - In the retry function, remove the
time.sleep()call. What happens conceptually when retrying against a struggling server? - Catch all exceptions with a bare
except:instead of specific exception types. Why is this dangerous?
Fix it¶
- After testing with
timeout=0, add a guard: if timeout is less than or equal to 0, set it to a reasonable default (like 10 seconds) and print a warning. - Replace the bare
except:with the specific exception types (requests.exceptions.RequestExceptionas a catch-all for requests errors). - After fixing, verify that each error scenario prints a clear, specific message about what went wrong.
Explain it¶
- What is the difference between
response.raise_for_status()and manually checkingresponse.status_code? - Why does exponential backoff use increasing delays (1s, 2s, 4s) instead of a fixed delay?
- What is the difference between a
ConnectionErrorand aTimeoutexception? - Why should you catch specific exceptions instead of using bare
except:?
Mastery check¶
You can move on when you can:
- name at least three types of request errors and their exception classes,
- implement a retry function with exponential backoff from memory,
- explain when to use
raise_for_status()vs manual status checks, - handle errors without crashing or printing raw tracebacks.
Related Concepts¶
Next¶
Continue to API Client Class.