0
# Path Operations
1
2
Navigate and extract values from deeply nested Python objects using string-based path notation. Provides utilities for path-based access to complex data structures, path parsing, and value extraction from arbitrary nesting levels.
3
4
## Capabilities
5
6
### Value Extraction
7
8
Extract values from nested objects using path notation that can navigate through dictionaries, lists, tuples, and other data structures.
9
10
```python { .api }
11
def extract(obj: Any, path: Union[str, List]) -> Any:
12
"""
13
Extract item from nested object using path notation.
14
15
Parameters:
16
- obj: Object to extract value from
17
- path: Path to the desired value (string or list format)
18
19
Returns:
20
The value found at the specified path.
21
22
Raises:
23
KeyError: If the path does not exist in the object
24
IndexError: If list/tuple index is out of range
25
AttributeError: If attribute does not exist on object
26
"""
27
```
28
29
### Path Parsing
30
31
Parse path strings into machine-readable format for programmatic path manipulation.
32
33
```python { .api }
34
def parse_path(path: str) -> List:
35
"""
36
Parse path string to machine-readable format.
37
38
Parameters:
39
- path: Path string in DeepDiff format (e.g., "root['key'][0]['subkey']")
40
41
Returns:
42
List of path components that can be used programmatically.
43
"""
44
```
45
46
47
## Usage Examples
48
49
### Basic Extraction
50
51
```python
52
from deepdiff import extract, parse_path
53
54
# Simple nested dictionary
55
data = {
56
"user": {
57
"name": "John",
58
"age": 30,
59
"address": {
60
"street": "123 Main St",
61
"city": "New York"
62
}
63
}
64
}
65
66
# Extract nested values
67
name = extract(data, "root['user']['name']")
68
print(name) # "John"
69
70
city = extract(data, "root['user']['address']['city']")
71
print(city) # "New York"
72
```
73
74
### Working with Lists and Mixed Structures
75
76
```python
77
# Complex nested structure with lists
78
data = {
79
"users": [
80
{"id": 1, "name": "John", "roles": ["admin", "user"]},
81
{"id": 2, "name": "Jane", "roles": ["user"]}
82
],
83
"settings": {
84
"permissions": {
85
"admin": ["read", "write", "delete"],
86
"user": ["read"]
87
}
88
}
89
}
90
91
# Extract from list by index
92
first_user = extract(data, "root['users'][0]")
93
print(first_user) # {"id": 1, "name": "John", "roles": ["admin", "user"]}
94
95
# Extract nested list item
96
first_role = extract(data, "root['users'][0]['roles'][0]")
97
print(first_role) # "admin"
98
99
# Extract from nested dictionary
100
admin_permissions = extract(data, "root['settings']['permissions']['admin']")
101
print(admin_permissions) # ["read", "write", "delete"]
102
```
103
104
### Path Parsing and Manipulation
105
106
```python
107
# Parse path string to components
108
path_str = "root['users'][0]['name']"
109
path_components = parse_path(path_str)
110
print(path_components) # ['users', 0, 'name']
111
112
# Use parsed components with extract
113
name = extract(data, path_components)
114
print(name) # "John"
115
116
# Convert components back to string
117
from deepdiff.path import to_string
118
reconstructed = to_string(path_components)
119
print(reconstructed) # "root['users'][0]['name']"
120
```
121
122
### Working with Custom Objects
123
124
```python
125
class Person:
126
def __init__(self, name, age):
127
self.name = name
128
self.age = age
129
130
class Company:
131
def __init__(self, name, employees):
132
self.name = name
133
self.employees = employees
134
135
# Create nested object structure
136
company = Company("TechCorp", [
137
Person("John", 30),
138
Person("Jane", 25)
139
])
140
141
# Extract from object attributes
142
company_name = extract(company, "root.name")
143
print(company_name) # "TechCorp"
144
145
first_employee_name = extract(company, "root.employees[0].name")
146
print(first_employee_name) # "John"
147
```
148
149
### Error Handling
150
151
```python
152
# Handle missing paths gracefully
153
try:
154
missing_value = extract(data, "root['nonexistent']['key']")
155
except KeyError as e:
156
print(f"Path not found: {e}")
157
158
try:
159
out_of_bounds = extract(data, "root['users'][999]['name']")
160
except IndexError as e:
161
print(f"Index out of range: {e}")
162
163
# Safe extraction with default values
164
def safe_extract(obj, path, default=None):
165
try:
166
return extract(obj, path)
167
except (KeyError, IndexError, AttributeError):
168
return default
169
170
value = safe_extract(data, "root['missing']['key']", "default")
171
print(value) # "default"
172
```
173
174
### Advanced Path Operations
175
176
```python
177
from deepdiff.path import GET, SET
178
179
# Use low-level path functions
180
path_components = ['users', 0, 'name']
181
182
# Get value using components
183
name = GET(data, path_components)
184
print(name) # "John"
185
186
# Set value using components (modifies original object)
187
SET(data, path_components, "Johnny")
188
updated_name = GET(data, path_components)
189
print(updated_name) # "Johnny"
190
```
191
192
### Working with Complex Path Patterns
193
194
```python
195
# Handle various path formats
196
data = {
197
"items": {
198
"item-1": {"value": 10},
199
"item_2": {"value": 20}
200
},
201
"list_items": [
202
{"key": "a", "value": 100},
203
{"key": "b", "value": 200}
204
]
205
}
206
207
# Extract with special characters in keys
208
value1 = extract(data, "root['items']['item-1']['value']")
209
print(value1) # 10
210
211
value2 = extract(data, "root['items']['item_2']['value']")
212
print(value2) # 20
213
214
# Find items by attribute value (requires custom logic)
215
def find_by_key(data, target_key):
216
for i, item in enumerate(data['list_items']):
217
if item['key'] == target_key:
218
return extract(data, f"root['list_items'][{i}]['value']")
219
return None
220
221
value_b = find_by_key(data, 'b')
222
print(value_b) # 200
223
```
224
225
### Integration with DeepDiff Results
226
227
```python
228
from deepdiff import DeepDiff
229
230
# Use extract with DeepDiff paths
231
original = {"user": {"name": "John", "age": 30}}
232
modified = {"user": {"name": "Jane", "age": 30}}
233
234
diff = DeepDiff(original, modified)
235
print(diff)
236
237
# Extract the paths that changed
238
if 'values_changed' in diff:
239
for path in diff['values_changed'].keys():
240
old_value = extract(original, path)
241
new_value = extract(modified, path)
242
print(f"Changed at {path}: {old_value} -> {new_value}")
243
```
244
245
### Batch Extraction
246
247
```python
248
# Extract multiple values efficiently
249
paths_to_extract = [
250
"root['users'][0]['name']",
251
"root['users'][1]['name']",
252
"root['settings']['permissions']['admin'][0]"
253
]
254
255
extracted_values = {}
256
for path in paths_to_extract:
257
try:
258
extracted_values[path] = extract(data, path)
259
except (KeyError, IndexError, AttributeError) as e:
260
extracted_values[path] = f"Error: {e}"
261
262
for path, value in extracted_values.items():
263
print(f"{path}: {value}")
264
```
265
266
## Types
267
268
```python { .api }
269
# Path representation types
270
PathString = str # String format: "root['key'][0]['subkey']"
271
PathList = List[Union[str, int]] # Component format: ['key', 0, 'subkey']
272
PathComponent = Union[str, int] # Individual path component
273
274
# Extraction result types
275
ExtractedValue = Any # Any value that can be extracted
276
ExtractedPath = Union[PathString, PathList]
277
278
# Error types for path operations
279
class PathError(Exception):
280
"""Base exception for path operations."""
281
282
class PathNotFoundError(PathError, KeyError):
283
"""Exception raised when a path does not exist."""
284
285
class PathIndexError(PathError, IndexError):
286
"""Exception raised when a list/tuple index is invalid."""
287
288
class PathAttributeError(PathError, AttributeError):
289
"""Exception raised when an attribute does not exist."""
290
```