0
# Exception Handling
1
2
Exception classes for handling errors during search operations including rate limiting, timeouts, and general API errors. All DDGS exceptions inherit from the base DDGSException class.
3
4
## Capabilities
5
6
### Base Exception
7
8
Base exception class that all DDGS-specific exceptions inherit from.
9
10
```python { .api }
11
class DDGSException(Exception):
12
"""
13
Base exception class for all ddgs-related errors.
14
15
This is the parent class for all exceptions raised by the DDGS library.
16
Catch this exception to handle any DDGS-related error generically.
17
"""
18
```
19
20
### Rate Limit Exception
21
22
Raised when search services return rate limit errors, indicating too many requests have been made in a short time period.
23
24
```python { .api }
25
class RatelimitException(DDGSException):
26
"""
27
Raised when rate limit is exceeded during API requests.
28
29
This exception is thrown when search backends indicate that
30
the request rate limit has been exceeded. The calling code
31
should implement backoff strategies when catching this exception.
32
"""
33
```
34
35
### Timeout Exception
36
37
Raised when search requests exceed the configured timeout period.
38
39
```python { .api }
40
class TimeoutException(DDGSException):
41
"""
42
Raised when API requests timeout.
43
44
This exception is thrown when search operations take longer
45
than the configured timeout value. Consider increasing the
46
timeout value or implementing retry logic.
47
"""
48
```
49
50
## Usage Examples
51
52
### Basic Exception Handling
53
54
```python
55
from ddgs import DDGS, DDGSException
56
57
try:
58
with DDGS() as ddgs:
59
results = ddgs.text("search query")
60
print(f"Found {len(results)} results")
61
except DDGSException as e:
62
print(f"Search failed: {e}")
63
```
64
65
### Specific Exception Handling
66
67
```python
68
from ddgs import DDGS, DDGSException, RatelimitException, TimeoutException
69
import time
70
71
def robust_search(query, max_retries=3, backoff_factor=2):
72
"""Perform search with retry logic for common exceptions."""
73
74
for attempt in range(max_retries):
75
try:
76
with DDGS(timeout=10) as ddgs:
77
return ddgs.text(query, max_results=20)
78
79
except RatelimitException:
80
if attempt < max_retries - 1:
81
wait_time = backoff_factor ** attempt
82
print(f"Rate limited. Waiting {wait_time} seconds before retry...")
83
time.sleep(wait_time)
84
continue
85
else:
86
print("Rate limit exceeded. Max retries reached.")
87
raise
88
89
except TimeoutException:
90
if attempt < max_retries - 1:
91
print(f"Request timed out. Retrying attempt {attempt + 2}...")
92
continue
93
else:
94
print("Request timed out. Max retries reached.")
95
raise
96
97
except DDGSException as e:
98
print(f"Search error: {e}")
99
raise
100
101
# Usage
102
try:
103
results = robust_search("python programming")
104
print(f"Successfully retrieved {len(results)} results")
105
except DDGSException as e:
106
print(f"All retry attempts failed: {e}")
107
```
108
109
### Exception Handling with Different Search Types
110
111
```python
112
from ddgs import DDGS, DDGSException, RatelimitException, TimeoutException
113
114
def safe_multi_search(query):
115
"""Perform multiple search types with proper exception handling."""
116
117
results = {
118
'text': [],
119
'images': [],
120
'news': [],
121
'videos': [],
122
'books': []
123
}
124
125
search_methods = [
126
('text', lambda ddgs: ddgs.text(query, max_results=10)),
127
('images', lambda ddgs: ddgs.images(query, max_results=5)),
128
('news', lambda ddgs: ddgs.news(query, max_results=5)),
129
('videos', lambda ddgs: ddgs.videos(query, max_results=5)),
130
('books', lambda ddgs: ddgs.books(query, max_results=5))
131
]
132
133
with DDGS(timeout=15) as ddgs:
134
for search_type, search_func in search_methods:
135
try:
136
results[search_type] = search_func(ddgs)
137
print(f"{search_type.title()} search: {len(results[search_type])} results")
138
139
except RatelimitException:
140
print(f"{search_type.title()} search rate limited, skipping...")
141
continue
142
143
except TimeoutException:
144
print(f"{search_type.title()} search timed out, skipping...")
145
continue
146
147
except DDGSException as e:
148
print(f"{search_type.title()} search failed: {e}")
149
continue
150
151
return results
152
153
# Usage
154
try:
155
all_results = safe_multi_search("artificial intelligence")
156
total_results = sum(len(results) for results in all_results.values())
157
print(f"Total results across all search types: {total_results}")
158
except Exception as e:
159
print(f"Unexpected error: {e}")
160
```
161
162
### Configuration-Based Exception Handling
163
164
```python
165
from ddgs import DDGS, DDGSException, RatelimitException, TimeoutException
166
167
class RobustDDGS:
168
"""Wrapper class with built-in exception handling and retry logic."""
169
170
def __init__(self, timeout=10, max_retries=3, backoff_factor=1.5):
171
self.timeout = timeout
172
self.max_retries = max_retries
173
self.backoff_factor = backoff_factor
174
175
def _execute_with_retry(self, search_func):
176
"""Execute search function with retry logic."""
177
last_exception = None
178
179
for attempt in range(self.max_retries):
180
try:
181
with DDGS(timeout=self.timeout) as ddgs:
182
return search_func(ddgs)
183
184
except RatelimitException as e:
185
last_exception = e
186
if attempt < self.max_retries - 1:
187
wait_time = self.backoff_factor ** attempt
188
time.sleep(wait_time)
189
continue
190
191
except TimeoutException as e:
192
last_exception = e
193
if attempt < self.max_retries - 1:
194
continue
195
196
except DDGSException as e:
197
# Don't retry for general DDGS exceptions
198
raise e
199
200
# If we get here, all retries failed
201
raise last_exception
202
203
def text(self, query, **kwargs):
204
"""Text search with automatic retry."""
205
return self._execute_with_retry(
206
lambda ddgs: ddgs.text(query, **kwargs)
207
)
208
209
def images(self, query, **kwargs):
210
"""Image search with automatic retry."""
211
return self._execute_with_retry(
212
lambda ddgs: ddgs.images(query, **kwargs)
213
)
214
215
# Similar methods for news, videos, books...
216
217
# Usage
218
robust_ddgs = RobustDDGS(timeout=15, max_retries=5)
219
220
try:
221
results = robust_ddgs.text("machine learning", max_results=50)
222
print(f"Retrieved {len(results)} results successfully")
223
except DDGSException as e:
224
print(f"Search failed after all retries: {e}")
225
```
226
227
## Best Practices
228
229
1. **Always use specific exception handling** - Catch `RatelimitException` and `TimeoutException` separately when you need different handling logic.
230
231
2. **Implement backoff strategies** - When catching `RatelimitException`, use exponential backoff before retrying.
232
233
3. **Set appropriate timeouts** - Balance between allowing enough time for searches and not hanging indefinitely.
234
235
4. **Use context managers** - Always use `with DDGS() as ddgs:` to ensure proper resource cleanup.
236
237
5. **Log exceptions for debugging** - Include exception details in logs to help diagnose issues.
238
239
6. **Graceful degradation** - Continue with available results even if some search types fail.
240
241
## Common Error Scenarios
242
243
- **Rate Limiting**: Occurs with high-frequency searches. Implement delays between requests.
244
- **Network Timeouts**: Common with slow internet or overloaded servers. Increase timeout values or retry.
245
- **Service Unavailability**: Individual search backends may be temporarily unavailable. Use "auto" backend for fallback.
246
- **Invalid Parameters**: Check query strings and parameter values before making requests.