0
# Exception Handling
1
2
Comprehensive exception hierarchy for handling various HTTP and network errors. urllib3 provides specific exceptions for different failure scenarios, enabling precise error handling and robust application design.
3
4
## Capabilities
5
6
### Base Exceptions
7
8
Foundation exceptions that all other urllib3 exceptions inherit from.
9
10
```python { .api }
11
class HTTPError(Exception):
12
"""Base exception used by urllib3."""
13
14
class HTTPWarning(Warning):
15
"""Base warning used by urllib3."""
16
```
17
18
### Pool-Related Exceptions
19
20
Exceptions related to connection pool management and state.
21
22
```python { .api }
23
class PoolError(HTTPError):
24
"""Base exception for errors caused within a pool."""
25
26
def __init__(self, pool, message: str):
27
"""
28
Parameters:
29
- pool: The connection pool where error occurred
30
- message: Error description
31
"""
32
33
class EmptyPoolError(PoolError):
34
"""Pool has no available connections."""
35
36
class FullPoolError(PoolError):
37
"""Pool is full and cannot accept new connections."""
38
39
class ClosedPoolError(PoolError):
40
"""Pool has been closed and cannot be used."""
41
```
42
43
### Request and Response Exceptions
44
45
Exceptions related to HTTP request and response processing.
46
47
```python { .api }
48
class RequestError(PoolError):
49
"""Base exception for request-related errors with URLs."""
50
51
def __init__(self, pool, url: str, message: str):
52
"""
53
Parameters:
54
- pool: Connection pool
55
- url: Request URL where error occurred
56
- message: Error description
57
"""
58
59
class MaxRetryError(RequestError):
60
"""Maximum number of retries exceeded."""
61
62
def __init__(self, pool, url: str, reason=None):
63
"""
64
Parameters:
65
- pool: Connection pool
66
- url: Request URL
67
- reason: Underlying exception that caused max retries
68
"""
69
70
class HostChangedError(RequestError):
71
"""Request made to different host than expected."""
72
73
class ResponseError(RequestError):
74
"""Too many error responses from server."""
75
76
class DecodeError(HTTPError):
77
"""Automatic content decoding failed."""
78
79
class ProtocolError(HTTPError):
80
"""Protocol-level error during request/response."""
81
82
# Backwards compatibility alias
83
ConnectionError = ProtocolError
84
85
class ResponseNotChunked(ProtocolError):
86
"""Response not chunked when chunked encoding expected."""
87
88
class BodyNotHttplibCompatible(HTTPError):
89
"""Request body not compatible with httplib."""
90
91
class IncompleteRead(HTTPError):
92
"""Response shorter than expected Content-Length."""
93
94
def __init__(self, partial: bytes, expected: int):
95
"""
96
Parameters:
97
- partial: Data received before connection closed
98
- expected: Expected number of bytes
99
"""
100
101
class InvalidChunkLength(HTTPError):
102
"""Invalid chunk length in chunked transfer encoding."""
103
104
class InvalidHeader(HTTPError):
105
"""Invalid header name or value format."""
106
107
class UnrewindableBodyError(HTTPError):
108
"""Cannot rewind request body for retry."""
109
```
110
111
### Timeout Exceptions
112
113
Exceptions related to request timeouts and timing issues.
114
115
```python { .api }
116
class TimeoutError(HTTPError):
117
"""Base timeout error."""
118
119
class TimeoutStateError(TimeoutError):
120
"""Invalid timeout state or configuration."""
121
122
class ReadTimeoutError(TimeoutError, RequestError):
123
"""Timeout while reading response data."""
124
125
class ConnectTimeoutError(TimeoutError, RequestError):
126
"""Timeout while establishing connection."""
127
```
128
129
### Connection Exceptions
130
131
Exceptions related to network connections and connectivity.
132
133
```python { .api }
134
class NewConnectionError(ConnectTimeoutError, PoolError):
135
"""Failed to establish new connection."""
136
137
class NameResolutionError(NewConnectionError):
138
"""DNS name resolution failed."""
139
```
140
141
### SSL/TLS Exceptions
142
143
Exceptions related to SSL/TLS certificate validation and secure connections.
144
145
```python { .api }
146
class SSLError(HTTPError):
147
"""SSL certificate or connection error."""
148
149
class CertificateError(SSLError):
150
"""SSL certificate validation error."""
151
```
152
153
### Proxy Exceptions
154
155
Exceptions related to proxy server connections and configuration.
156
157
```python { .api }
158
class ProxyError(HTTPError):
159
"""Proxy connection error."""
160
161
def __init__(self, message: str, error: Exception):
162
"""
163
Parameters:
164
- message: Error description
165
- error: Original underlying error
166
"""
167
168
class ProxySchemeUnknown(AssertionError, ValueError):
169
"""Unknown proxy scheme in proxy URL."""
170
171
class ProxySchemeUnsupported(ValueError):
172
"""Unsupported proxy scheme."""
173
```
174
175
### URL and Location Exceptions
176
177
Exceptions related to URL parsing and validation.
178
179
```python { .api }
180
class LocationValueError(ValueError, HTTPError):
181
"""Invalid URL input or host specification."""
182
183
class LocationParseError(LocationValueError):
184
"""Failed to parse URL components."""
185
186
class URLSchemeUnknown(LocationValueError):
187
"""Unknown URL scheme."""
188
189
class HeaderParsingError(HTTPError):
190
"""Failed to parse HTTP headers."""
191
```
192
193
### Warning Classes
194
195
Warning categories for non-fatal issues that should be brought to attention.
196
197
```python { .api }
198
class SecurityWarning(HTTPWarning):
199
"""Security-related warnings (unverified HTTPS, weak SSL, etc.)."""
200
201
class InsecureRequestWarning(SecurityWarning):
202
"""Unverified HTTPS request warning."""
203
204
class NotOpenSSLWarning(SecurityWarning):
205
"""Non-OpenSSL SSL library in use warning."""
206
207
class SystemTimeWarning(SecurityWarning):
208
"""System time appears incorrect warning."""
209
210
class InsecurePlatformWarning(SecurityWarning):
211
"""Platform missing SSL/TLS security features warning."""
212
213
class DependencyWarning(HTTPWarning):
214
"""Missing optional dependencies warning."""
215
```
216
217
## Usage Examples
218
219
### Basic Exception Handling
220
221
```python
222
import urllib3
223
224
http = urllib3.PoolManager()
225
226
try:
227
resp = http.request('GET', 'https://nonexistent.example.com')
228
except urllib3.exceptions.NewConnectionError as e:
229
print(f"Connection failed: {e}")
230
except urllib3.exceptions.TimeoutError as e:
231
print(f"Request timed out: {e}")
232
except urllib3.exceptions.HTTPError as e:
233
print(f"HTTP error: {e}")
234
```
235
236
### Retry Exception Handling
237
238
```python
239
import urllib3
240
241
http = urllib3.PoolManager(retries=urllib3.Retry(total=3))
242
243
try:
244
resp = http.request('GET', 'https://httpbin.org/status/500')
245
except urllib3.exceptions.MaxRetryError as e:
246
print(f"Max retries exceeded: {e}")
247
print(f"Original error: {e.reason}")
248
print(f"Failed URL: {e.url}")
249
```
250
251
### SSL/TLS Exception Handling
252
253
```python
254
import urllib3
255
256
# Disable SSL warnings for this example
257
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
258
259
http = urllib3.PoolManager()
260
261
try:
262
# This will raise an SSL error due to certificate issues
263
resp = http.request('GET', 'https://self-signed.badssl.com/')
264
except urllib3.exceptions.SSLError as e:
265
print(f"SSL error: {e}")
266
except urllib3.exceptions.CertificateError as e:
267
print(f"Certificate error: {e}")
268
```
269
270
### Timeout Exception Handling
271
272
```python
273
import urllib3
274
275
http = urllib3.PoolManager(timeout=urllib3.Timeout(total=1.0))
276
277
try:
278
# This will timeout
279
resp = http.request('GET', 'https://httpbin.org/delay/5')
280
except urllib3.exceptions.ConnectTimeoutError as e:
281
print(f"Connection timeout: {e}")
282
except urllib3.exceptions.ReadTimeoutError as e:
283
print(f"Read timeout: {e}")
284
except urllib3.exceptions.TimeoutError as e:
285
print(f"General timeout: {e}")
286
```
287
288
### Pool Exception Handling
289
290
```python
291
import urllib3
292
293
# Create pool with limited connections
294
pool = urllib3.HTTPConnectionPool('httpbin.org', maxsize=1, block=False)
295
296
try:
297
# First request will succeed
298
resp1 = pool.urlopen('GET', '/delay/1', preload_content=False)
299
300
# Second request will fail because pool is full and block=False
301
resp2 = pool.urlopen('GET', '/delay/1')
302
303
except urllib3.exceptions.FullPoolError as e:
304
print(f"Pool is full: {e}")
305
finally:
306
pool.close()
307
```
308
309
### Proxy Exception Handling
310
311
```python
312
import urllib3
313
314
try:
315
# Invalid proxy URL
316
proxy = urllib3.ProxyManager('invalid://proxy.example.com')
317
except urllib3.exceptions.ProxySchemeUnknown as e:
318
print(f"Unknown proxy scheme: {e}")
319
320
try:
321
# Valid proxy but connection fails
322
proxy = urllib3.ProxyManager('http://nonexistent-proxy.example.com:8080')
323
resp = proxy.request('GET', 'https://httpbin.org/get')
324
except urllib3.exceptions.ProxyError as e:
325
print(f"Proxy error: {e}")
326
print(f"Original error: {e.original_error}")
327
```
328
329
### Comprehensive Error Handling
330
331
```python
332
import urllib3
333
334
def make_request(url, retries=3, timeout=10):
335
"""Make HTTP request with comprehensive error handling."""
336
337
http = urllib3.PoolManager(
338
retries=urllib3.Retry(total=retries),
339
timeout=urllib3.Timeout(total=timeout)
340
)
341
342
try:
343
resp = http.request('GET', url)
344
return resp.status, resp.data
345
346
except urllib3.exceptions.MaxRetryError as e:
347
if isinstance(e.reason, urllib3.exceptions.NewConnectionError):
348
return None, f"Connection failed: {e.reason}"
349
elif isinstance(e.reason, urllib3.exceptions.TimeoutError):
350
return None, f"Request timed out: {e.reason}"
351
else:
352
return None, f"Max retries exceeded: {e.reason}"
353
354
except urllib3.exceptions.SSLError as e:
355
return None, f"SSL/TLS error: {e}"
356
357
except urllib3.exceptions.LocationValueError as e:
358
return None, f"Invalid URL: {e}"
359
360
except urllib3.exceptions.HTTPError as e:
361
return None, f"HTTP error: {e}"
362
363
except Exception as e:
364
return None, f"Unexpected error: {e}"
365
366
# Usage
367
status, result = make_request('https://httpbin.org/get')
368
if status:
369
print(f"Success: {status}")
370
else:
371
print(f"Error: {result}")
372
```
373
374
### Response Processing with Error Handling
375
376
```python
377
import urllib3
378
import json
379
380
def get_json_data(url):
381
"""Get JSON data with comprehensive error handling."""
382
383
http = urllib3.PoolManager()
384
385
try:
386
resp = http.request('GET', url)
387
388
if resp.status != 200:
389
raise urllib3.exceptions.HTTPError(f"HTTP {resp.status}: {resp.reason}")
390
391
try:
392
return resp.json()
393
except (json.JSONDecodeError, UnicodeDecodeError) as e:
394
raise urllib3.exceptions.DecodeError(f"Failed to decode JSON: {e}")
395
396
except urllib3.exceptions.DecodeError:
397
raise # Re-raise decode errors
398
except urllib3.exceptions.HTTPError:
399
raise # Re-raise HTTP errors
400
except Exception as e:
401
raise urllib3.exceptions.HTTPError(f"Unexpected error: {e}")
402
403
# Usage with error handling
404
try:
405
data = get_json_data('https://jsonplaceholder.typicode.com/posts/1')
406
print(f"Title: {data.get('title')}")
407
except urllib3.exceptions.DecodeError as e:
408
print(f"JSON decode error: {e}")
409
except urllib3.exceptions.HTTPError as e:
410
print(f"HTTP error: {e}")
411
```
412
413
### Warning Management
414
415
```python
416
import urllib3
417
import warnings
418
419
# Disable specific warnings
420
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
421
422
# Or disable all urllib3 warnings
423
urllib3.disable_warnings()
424
425
# Custom warning handling
426
def custom_warning_handler(message, category, filename, lineno, file=None, line=None):
427
if category == urllib3.exceptions.InsecureRequestWarning:
428
print(f"Security warning: {message}")
429
else:
430
print(f"Other warning: {message}")
431
432
# Set custom warning handler
433
warnings.showwarning = custom_warning_handler
434
435
# Make request that would normally generate warning
436
http = urllib3.PoolManager()
437
resp = http.request('GET', 'https://self-signed.badssl.com/', verify=False)
438
```
439
440
## Exception Hierarchy
441
442
The urllib3 exception hierarchy allows for precise error handling:
443
444
```
445
Exception
446
├── HTTPError (base for all urllib3 errors)
447
│ ├── PoolError
448
│ │ ├── EmptyPoolError
449
│ │ ├── FullPoolError
450
│ │ ├── ClosedPoolError
451
│ │ └── RequestError
452
│ │ ├── MaxRetryError
453
│ │ ├── HostChangedError
454
│ │ └── ResponseError
455
│ ├── TimeoutError
456
│ │ ├── TimeoutStateError
457
│ │ ├── ReadTimeoutError
458
│ │ └── ConnectTimeoutError
459
│ ├── SSLError
460
│ │ └── CertificateError
461
│ ├── ProxyError
462
│ ├── DecodeError
463
│ ├── ProtocolError (ConnectionError)
464
│ ├── LocationValueError
465
│ │ ├── LocationParseError
466
│ │ └── URLSchemeUnknown
467
│ └── Various other specific errors...
468
│
469
└── Warning
470
└── HTTPWarning
471
├── SecurityWarning
472
│ ├── InsecureRequestWarning
473
│ ├── NotOpenSSLWarning
474
│ ├── SystemTimeWarning
475
│ └── InsecurePlatformWarning
476
└── DependencyWarning
477
```
478
479
This hierarchy allows catching errors at different levels of specificity based on your application's needs.