Enforcing Limits on Calls with Timeout Arguments
๐ท๏ธ APIs and HTTP Requests / Timeouts and Error Handling
When making HTTP requests, your code may sometimes wait indefinitely for a response. A server could be slow, unresponsive, or simply down. Without a timeout, your program will hang, blocking all further execution. Setting a timeout argument tells your code: "If no response arrives within this many seconds, give up and raise an error." This simple practice prevents your scripts from freezing and helps you build resilient, production-ready applications.
โ๏ธ What Is a Timeout?
A timeout is a maximum waiting period you define for a network call. If the server does not respond within that time, the request is cancelled and an exception is raised.
- Connection timeout โ The time allowed to establish a connection to the server.
- Read timeout โ The time allowed to receive data after the connection is made.
- Combined timeout โ A single value that applies to both connection and read phases.
๐ ๏ธ How to Set a Timeout in Python
The requests library accepts a timeout parameter in its HTTP methods. You pass a number (in seconds) or a tuple for separate connection and read limits.
Single timeout value (applies to both phases): - requests.get('https://api.example.com/data', timeout=5) โ Waits up to 5 seconds for the entire operation.
Separate connection and read timeouts: - requests.get('https://api.example.com/data', timeout=(3, 10)) โ Allows 3 seconds to connect, then 10 seconds to receive the response.
No timeout (dangerous, avoid in production): - requests.get('https://api.example.com/data', timeout=None) โ Waits forever. Your script will hang if the server never responds.
๐ Timeout Behavior Comparison
| Timeout Setting | Connection Limit | Read Limit | Behavior on Timeout |
|---|---|---|---|
| timeout=5 | 5 seconds | 5 seconds | Raises requests.exceptions.ConnectTimeout or ReadTimeout |
| timeout=(3, 10) | 3 seconds | 10 seconds | Raises requests.exceptions.ConnectTimeout or ReadTimeout |
| timeout=None | No limit | No limit | Waits indefinitely (script may hang) |
| timeout=0.5 | 0.5 seconds | 0.5 seconds | Very strict โ useful for health checks |
๐ต๏ธ Handling Timeout Errors Gracefully
When a timeout occurs, Python raises an exception. You should catch it and decide how to proceed โ retry, log the failure, or return a fallback value.
Basic try-except pattern: - Wrap your request in a try block. - Catch requests.exceptions.Timeout (parent of both ConnectTimeout and ReadTimeout). - In the except block, log the error or implement a retry logic.
Example flow: - try: response = requests.get('https://api.example.com/data', timeout=5) - except requests.exceptions.Timeout: print("Request timed out. The server may be slow or unreachable.") - else: process the response normally
๐ Best Practices for Engineers
- Always set a timeout โ Never leave timeout as None in production code. A missing timeout is a common source of stuck processes.
- Use separate timeouts for connection and read โ A short connection timeout (2โ3 seconds) catches unreachable servers quickly. A longer read timeout (10โ30 seconds) allows for slow but healthy responses.
- Set timeouts based on your use case โ A health check endpoint might use 1 second. A data export endpoint might use 60 seconds.
- Log timeout events โ Record when timeouts occur so you can monitor server performance and adjust limits.
- Consider retry logic โ A single timeout may be temporary. Retrying once or twice with exponential backoff can improve reliability.
๐งช Common Pitfalls to Avoid
- Forgetting the timeout parameter entirely โ The request will wait forever by default.
- Setting timeouts too short โ Legitimate slow responses will fail unnecessarily. Test with real server response times.
- Setting timeouts too long โ Your application becomes unresponsive during failures. Balance user experience with server capabilities.
- Not catching the timeout exception โ An unhandled timeout will crash your script or API endpoint.
๐ Putting It All Together
A robust HTTP call with timeouts follows this pattern:
- Define a reasonable timeout value (or tuple) for your endpoint.
- Make the request inside a try block.
- Catch requests.exceptions.Timeout and handle it gracefully.
- Optionally, catch other exceptions like ConnectionError or RequestException for broader error handling.
- Log the outcome for monitoring and debugging.
By enforcing timeouts on every external call, you protect your applications from hanging indefinitely, improve user experience, and build systems that fail fast and recover gracefully.
Timeout arguments set a maximum wait time for API calls, preventing your code from hanging indefinitely when a server is slow or unresponsive.
๐งช Example 1: Basic timeout with requests.get
This shows how to set a simple 3-second timeout on a GET request.
import requests
response = requests.get("https://httpbin.org/delay/5", timeout=3)
๐ค Output: requests.exceptions.Timeout: The request timed out
๐งช Example 2: Separate connect and read timeouts
This demonstrates setting different time limits for connecting to the server versus waiting for data.
import requests
response = requests.get(
"https://httpbin.org/delay/2",
timeout=(2, 3)
)
๐ค Output:
๐งช Example 3: Catching timeout exceptions gracefully
This shows how to handle a timeout error so your program doesn't crash.
import requests
try:
response = requests.get("https://httpbin.org/delay/10", timeout=2)
print("Success:", response.status_code)
except requests.exceptions.Timeout:
print("The request timed out after 2 seconds")
๐ค Output: The request timed out after 2 seconds
๐งช Example 4: Using timeout with POST requests
This demonstrates applying a timeout when sending data to an API.
import requests
data = {"user": "engineer", "action": "deploy"}
try:
response = requests.post(
"https://httpbin.org/post",
json=data,
timeout=5
)
print("Response received:", response.json()["json"])
except requests.exceptions.Timeout:
print("POST request timed out")
๐ค Output: Response received: {'user': 'engineer', 'action': 'deploy'}
๐งช Example 5: Timeout with session for multiple calls
This shows how to set a default timeout for all requests made through a session.
import requests
session = requests.Session()
session.timeout = 3
urls = [
"https://httpbin.org/delay/1",
"https://httpbin.org/delay/4",
"https://httpbin.org/delay/2"
]
for url in urls:
try:
resp = session.get(url)
print(f"{url} -> Status: {resp.status_code}")
except requests.exceptions.Timeout:
print(f"{url} -> Timed out")
๐ค Output: https://httpbin.org/delay/1 -> Status: 200
https://httpbin.org/delay/4 -> Timed out
https://httpbin.org/delay/2 -> Status: 200
๐ Comparison Table
| Timeout Type | Syntax | Use Case |
|---|---|---|
| Single timeout | timeout=5 |
Simple wait limit for entire request |
| Connect/Read split | timeout=(2, 5) |
Different limits for connecting vs receiving data |
| Session default | session.timeout = 3 |
Consistent timeout across many requests |
| No timeout | timeout=None |
Only for trusted local APIs (not recommended) |
When making HTTP requests, your code may sometimes wait indefinitely for a response. A server could be slow, unresponsive, or simply down. Without a timeout, your program will hang, blocking all further execution. Setting a timeout argument tells your code: "If no response arrives within this many seconds, give up and raise an error." This simple practice prevents your scripts from freezing and helps you build resilient, production-ready applications.
โ๏ธ What Is a Timeout?
A timeout is a maximum waiting period you define for a network call. If the server does not respond within that time, the request is cancelled and an exception is raised.
- Connection timeout โ The time allowed to establish a connection to the server.
- Read timeout โ The time allowed to receive data after the connection is made.
- Combined timeout โ A single value that applies to both connection and read phases.
๐ ๏ธ How to Set a Timeout in Python
The requests library accepts a timeout parameter in its HTTP methods. You pass a number (in seconds) or a tuple for separate connection and read limits.
Single timeout value (applies to both phases): - requests.get('https://api.example.com/data', timeout=5) โ Waits up to 5 seconds for the entire operation.
Separate connection and read timeouts: - requests.get('https://api.example.com/data', timeout=(3, 10)) โ Allows 3 seconds to connect, then 10 seconds to receive the response.
No timeout (dangerous, avoid in production): - requests.get('https://api.example.com/data', timeout=None) โ Waits forever. Your script will hang if the server never responds.
๐ Timeout Behavior Comparison
| Timeout Setting | Connection Limit | Read Limit | Behavior on Timeout |
|---|---|---|---|
| timeout=5 | 5 seconds | 5 seconds | Raises requests.exceptions.ConnectTimeout or ReadTimeout |
| timeout=(3, 10) | 3 seconds | 10 seconds | Raises requests.exceptions.ConnectTimeout or ReadTimeout |
| timeout=None | No limit | No limit | Waits indefinitely (script may hang) |
| timeout=0.5 | 0.5 seconds | 0.5 seconds | Very strict โ useful for health checks |
๐ต๏ธ Handling Timeout Errors Gracefully
When a timeout occurs, Python raises an exception. You should catch it and decide how to proceed โ retry, log the failure, or return a fallback value.
Basic try-except pattern: - Wrap your request in a try block. - Catch requests.exceptions.Timeout (parent of both ConnectTimeout and ReadTimeout). - In the except block, log the error or implement a retry logic.
Example flow: - try: response = requests.get('https://api.example.com/data', timeout=5) - except requests.exceptions.Timeout: print("Request timed out. The server may be slow or unreachable.") - else: process the response normally
๐ Best Practices for Engineers
- Always set a timeout โ Never leave timeout as None in production code. A missing timeout is a common source of stuck processes.
- Use separate timeouts for connection and read โ A short connection timeout (2โ3 seconds) catches unreachable servers quickly. A longer read timeout (10โ30 seconds) allows for slow but healthy responses.
- Set timeouts based on your use case โ A health check endpoint might use 1 second. A data export endpoint might use 60 seconds.
- Log timeout events โ Record when timeouts occur so you can monitor server performance and adjust limits.
- Consider retry logic โ A single timeout may be temporary. Retrying once or twice with exponential backoff can improve reliability.
๐งช Common Pitfalls to Avoid
- Forgetting the timeout parameter entirely โ The request will wait forever by default.
- Setting timeouts too short โ Legitimate slow responses will fail unnecessarily. Test with real server response times.
- Setting timeouts too long โ Your application becomes unresponsive during failures. Balance user experience with server capabilities.
- Not catching the timeout exception โ An unhandled timeout will crash your script or API endpoint.
๐ Putting It All Together
A robust HTTP call with timeouts follows this pattern:
- Define a reasonable timeout value (or tuple) for your endpoint.
- Make the request inside a try block.
- Catch requests.exceptions.Timeout and handle it gracefully.
- Optionally, catch other exceptions like ConnectionError or RequestException for broader error handling.
- Log the outcome for monitoring and debugging.
By enforcing timeouts on every external call, you protect your applications from hanging indefinitely, improve user experience, and build systems that fail fast and recover gracefully.
Interactive Views
You are currently in ๐ All-in-One mode. Use the tabs at the top to switch to ๐ Theory Only or ๐ป Code Only views.
Timeout arguments set a maximum wait time for API calls, preventing your code from hanging indefinitely when a server is slow or unresponsive.
๐งช Example 1: Basic timeout with requests.get
This shows how to set a simple 3-second timeout on a GET request.
import requests
response = requests.get("https://httpbin.org/delay/5", timeout=3)
๐ค Output: requests.exceptions.Timeout: The request timed out
๐งช Example 2: Separate connect and read timeouts
This demonstrates setting different time limits for connecting to the server versus waiting for data.
import requests
response = requests.get(
"https://httpbin.org/delay/2",
timeout=(2, 3)
)
๐ค Output:
๐งช Example 3: Catching timeout exceptions gracefully
This shows how to handle a timeout error so your program doesn't crash.
import requests
try:
response = requests.get("https://httpbin.org/delay/10", timeout=2)
print("Success:", response.status_code)
except requests.exceptions.Timeout:
print("The request timed out after 2 seconds")
๐ค Output: The request timed out after 2 seconds
๐งช Example 4: Using timeout with POST requests
This demonstrates applying a timeout when sending data to an API.
import requests
data = {"user": "engineer", "action": "deploy"}
try:
response = requests.post(
"https://httpbin.org/post",
json=data,
timeout=5
)
print("Response received:", response.json()["json"])
except requests.exceptions.Timeout:
print("POST request timed out")
๐ค Output: Response received: {'user': 'engineer', 'action': 'deploy'}
๐งช Example 5: Timeout with session for multiple calls
This shows how to set a default timeout for all requests made through a session.
import requests
session = requests.Session()
session.timeout = 3
urls = [
"https://httpbin.org/delay/1",
"https://httpbin.org/delay/4",
"https://httpbin.org/delay/2"
]
for url in urls:
try:
resp = session.get(url)
print(f"{url} -> Status: {resp.status_code}")
except requests.exceptions.Timeout:
print(f"{url} -> Timed out")
๐ค Output: https://httpbin.org/delay/1 -> Status: 200
https://httpbin.org/delay/4 -> Timed out
https://httpbin.org/delay/2 -> Status: 200
๐ Comparison Table
| Timeout Type | Syntax | Use Case |
|---|---|---|
| Single timeout | timeout=5 |
Simple wait limit for entire request |
| Connect/Read split | timeout=(2, 5) |
Different limits for connecting vs receiving data |
| Session default | session.timeout = 3 |
Consistent timeout across many requests |
| No timeout | timeout=None |
Only for trusted local APIs (not recommended) |