docs
0
# Paging and Result Iteration
1
2
Azure Core provides comprehensive pagination support for handling large result sets from Azure services. The paging system supports both synchronous and asynchronous operations with automatic continuation token management, error recovery, and flexible iteration patterns.
3
4
## Core Components
5
6
### ItemPaged
7
8
Iterator for paging through individual items across multiple pages with lazy evaluation and continuation token support.
9
10
```python { .api }
11
from azure.core.paging import ItemPaged
12
from typing import Iterator, Optional, TypeVar, Callable, Tuple, Iterable, Any
13
14
ReturnType = TypeVar('ReturnType')
15
ResponseType = TypeVar('ResponseType')
16
17
class ItemPaged(Iterator[ReturnType]):
18
def __init__(
19
self,
20
get_next: Callable[[Optional[str]], ResponseType],
21
extract_data: Callable[[ResponseType], Tuple[str, Iterable[ReturnType]]],
22
continuation_token: Optional[str] = None,
23
*,
24
page_iterator_class: type = PageIterator
25
): ...
26
27
def by_page(self, continuation_token: Optional[str] = None) -> Iterator[Iterator[ReturnType]]: ...
28
29
def __iter__(self) -> Iterator[ReturnType]: ...
30
31
def __next__(self) -> ReturnType: ...
32
```
33
34
### PageIterator
35
36
Iterator for accessing results page by page with continuation token management and error recovery.
37
38
```python { .api }
39
from azure.core.paging import PageIterator
40
41
class PageIterator(Iterator[Iterator[ReturnType]]):
42
def __init__(
43
self,
44
get_next: Callable[[Optional[str]], ResponseType],
45
extract_data: Callable[[ResponseType], Tuple[str, Iterable[ReturnType]]],
46
continuation_token: Optional[str] = None,
47
): ...
48
49
def __iter__(self) -> Iterator[Iterator[ReturnType]]: ...
50
51
def __next__(self) -> Iterator[ReturnType]: ...
52
```
53
54
## Basic Usage
55
56
### Item-by-Item Iteration
57
58
```python
59
from azure.core.paging import ItemPaged
60
61
def get_next(continuation_token=None):
62
"""Fetch next page of results from service"""
63
if not continuation_token:
64
return {
65
"nextLink": "page2",
66
"value": ["item1", "item2", "item3"]
67
}
68
elif continuation_token == "page2":
69
return {
70
"nextLink": None,
71
"value": ["item4", "item5"]
72
}
73
return {"nextLink": None, "value": []}
74
75
def extract_data(response):
76
"""Extract continuation token and items from response"""
77
next_link = response.get("nextLink")
78
items = response.get("value", [])
79
return next_link, iter(items)
80
81
# Create pager and iterate over all items
82
pager = ItemPaged(get_next, extract_data)
83
84
# Iterate through all items across all pages
85
all_items = []
86
for item in pager:
87
all_items.append(item)
88
print(f"Got item: {item}")
89
90
# Result: ["item1", "item2", "item3", "item4", "item5"]
91
```
92
93
### Page-by-Page Iteration
94
95
```python
96
# Iterate page by page for more control
97
pager = ItemPaged(get_next, extract_data)
98
99
for page in pager.by_page():
100
page_items = list(page)
101
print(f"Page contains {len(page_items)} items: {page_items}")
102
103
# Process each item in the current page
104
for item in page_items:
105
process_item(item)
106
```
107
108
### Continuation Token Usage
109
110
```python
111
# Start from beginning
112
pager = ItemPaged(get_next, extract_data)
113
114
# Get some items and stop
115
items_so_far = []
116
page_iter = pager.by_page()
117
118
# Process first page
119
first_page = next(page_iter)
120
items_so_far.extend(list(first_page))
121
122
# Resume from a specific token later
123
token = "page2" # This would come from your service
124
resumed_pager = ItemPaged(get_next, extract_data).by_page(continuation_token=token)
125
126
for page in resumed_pager:
127
remaining_items = list(page)
128
items_so_far.extend(remaining_items)
129
```
130
131
## Async Support
132
133
### AsyncItemPaged
134
135
Asynchronous version of ItemPaged for use with async/await patterns.
136
137
```python { .api }
138
from azure.core.async_paging import AsyncItemPaged
139
from typing import AsyncIterator, Awaitable
140
141
class AsyncItemPaged(AsyncIterator[ReturnType]):
142
def __init__(
143
self,
144
get_next: Callable[[Optional[str]], Awaitable[ResponseType]],
145
extract_data: Callable[[ResponseType], Awaitable[Tuple[str, AsyncIterator[ReturnType]]]],
146
continuation_token: Optional[str] = None,
147
*,
148
page_iterator_class: type = AsyncPageIterator
149
): ...
150
151
def by_page(self, continuation_token: Optional[str] = None) -> AsyncIterator[AsyncIterator[ReturnType]]: ...
152
153
async def __anext__(self) -> ReturnType: ...
154
```
155
156
### AsyncPageIterator
157
158
Asynchronous page iterator with async continuation token handling.
159
160
```python { .api }
161
from azure.core.async_paging import AsyncPageIterator
162
163
class AsyncPageIterator(AsyncIterator[AsyncIterator[ReturnType]]):
164
def __init__(
165
self,
166
get_next: Callable[[Optional[str]], Awaitable[ResponseType]],
167
extract_data: Callable[[ResponseType], Awaitable[Tuple[str, AsyncIterator[ReturnType]]]],
168
continuation_token: Optional[str] = None,
169
): ...
170
171
async def __anext__(self) -> AsyncIterator[ReturnType]: ...
172
```
173
174
### Async Usage Examples
175
176
```python
177
import asyncio
178
from azure.core.async_paging import AsyncItemPaged, AsyncList
179
180
async def async_get_next(continuation_token=None):
181
"""Async version of get_next"""
182
await asyncio.sleep(0.1) # Simulate API call
183
if not continuation_token:
184
return {
185
"nextLink": "page2",
186
"value": ["async_item1", "async_item2"]
187
}
188
elif continuation_token == "page2":
189
return {
190
"nextLink": None,
191
"value": ["async_item3", "async_item4"]
192
}
193
return {"nextLink": None, "value": []}
194
195
async def async_extract_data(response):
196
"""Extract data for async iteration"""
197
next_link = response.get("nextLink")
198
items = response.get("value", [])
199
# Wrap sync iterable for async iteration
200
return next_link, AsyncList(items)
201
202
async def async_paging_example():
203
# Async item-by-item iteration
204
pager = AsyncItemPaged(async_get_next, async_extract_data)
205
206
async for item in pager:
207
print(f"Async item: {item}")
208
209
# Async page-by-page iteration
210
pager = AsyncItemPaged(async_get_next, async_extract_data)
211
212
async for page in pager.by_page():
213
async for item in page:
214
print(f"Page item: {item}")
215
216
# Run the async example
217
asyncio.run(async_paging_example())
218
```
219
220
## Real-World Service Integration
221
222
### Azure Service Client Pattern
223
224
```python
225
from azure.core.paging import ItemPaged
226
from azure.core import PipelineClient
227
228
class MyAzureServiceClient:
229
def __init__(self, endpoint: str, credential):
230
self._client = PipelineClient(base_url=endpoint, credential=credential)
231
232
def list_resources(self, **kwargs) -> ItemPaged[dict]:
233
"""List resources with automatic paging"""
234
235
def get_next(next_link=None):
236
if next_link:
237
# Use provided next link
238
request = HttpRequest("GET", next_link)
239
else:
240
# Build initial request
241
request = HttpRequest("GET", "/api/resources")
242
if kwargs.get('filter'):
243
request.url += f"?$filter={kwargs['filter']}"
244
245
# Execute request through pipeline
246
response = self._client.send_request(request)
247
response.raise_for_status()
248
return response.json()
249
250
def extract_data(response_data):
251
# Extract items and continuation token from response
252
items = response_data.get("value", [])
253
next_link = response_data.get("nextLink") or response_data.get("@odata.nextLink")
254
return next_link, iter(items)
255
256
return ItemPaged(get_next, extract_data)
257
258
# Usage
259
client = MyAzureServiceClient("https://api.service.azure.com", credential)
260
261
# Iterate over all resources across all pages
262
for resource in client.list_resources(filter="status eq 'active'"):
263
print(f"Resource: {resource['name']}")
264
265
# Or process page by page for better memory management
266
for page in client.list_resources().by_page():
267
resources = list(page)
268
print(f"Processing {len(resources)} resources in this page")
269
process_resource_batch(resources)
270
```
271
272
### Error Handling and Recovery
273
274
```python
275
from azure.core.exceptions import AzureError
276
277
def robust_paging_example():
278
pager = ItemPaged(get_next, extract_data)
279
page_iterator = pager.by_page()
280
281
processed_items = []
282
continuation_token = None
283
284
try:
285
for page in page_iterator:
286
# Process current page
287
page_items = list(page)
288
processed_items.extend(page_items)
289
290
# Save progress periodically
291
if len(processed_items) % 100 == 0:
292
save_progress(processed_items, continuation_token)
293
294
except AzureError as e:
295
print(f"Error occurred: {e}")
296
# The iterator preserves continuation token for recovery
297
if hasattr(page_iterator, 'continuation_token'):
298
print(f"Can resume from token: {page_iterator.continuation_token}")
299
# Resume processing later
300
resumed_pager = ItemPaged(get_next, extract_data).by_page(
301
continuation_token=page_iterator.continuation_token
302
)
303
```
304
305
## Advanced Features
306
307
### Custom Page Iterator
308
309
```python
310
class CustomPageIterator(PageIterator):
311
def __init__(self, *args, **kwargs):
312
super().__init__(*args, **kwargs)
313
self.pages_processed = 0
314
315
def __next__(self):
316
result = super().__next__()
317
self.pages_processed += 1
318
print(f"Processed {self.pages_processed} pages so far")
319
return result
320
321
# Use custom page iterator
322
pager = ItemPaged(
323
get_next,
324
extract_data,
325
page_iterator_class=CustomPageIterator
326
)
327
```
328
329
### Memory-Efficient Processing
330
331
```python
332
def process_large_dataset(pager: ItemPaged, batch_size: int = 100):
333
"""Process large datasets in batches to manage memory usage"""
334
batch = []
335
336
for item in pager:
337
batch.append(item)
338
339
if len(batch) >= batch_size:
340
# Process batch and clear memory
341
process_batch(batch)
342
batch.clear()
343
344
# Process remaining items
345
if batch:
346
process_batch(batch)
347
348
# Usage with a service that returns millions of items
349
large_pager = client.list_all_items()
350
process_large_dataset(large_pager, batch_size=1000)
351
```
352
353
## Key Features
354
355
**Lazy Evaluation**: Items and pages are fetched on-demand, minimizing memory usage for large datasets.
356
357
**Continuation Token Support**: Built-in support for resuming interrupted operations from any point.
358
359
**Error Recovery**: Errors preserve continuation state, allowing for robust error handling and recovery.
360
361
**Type Safety**: Full generic typing support with proper type hints for items and responses.
362
363
**Dual Interface**: Both item-by-item and page-by-page iteration patterns for different use cases.
364
365
**Sync/Async Parity**: Matching APIs for both synchronous and asynchronous operations.
366
367
**Flexible Construction**: Support for custom page iterator classes and extraction logic.
368
369
The paging system provides a robust, efficient way to handle large result sets from Azure services while maintaining simplicity for common use cases and flexibility for advanced scenarios.