Deep Difference and Search of any Python object/data with delta and hash capabilities.
—
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.
Extract values from nested objects using path notation that can navigate through dictionaries, lists, tuples, and other data structures.
def extract(obj: Any, path: Union[str, List]) -> Any:
"""
Extract item from nested object using path notation.
Parameters:
- obj: Object to extract value from
- path: Path to the desired value (string or list format)
Returns:
The value found at the specified path.
Raises:
KeyError: If the path does not exist in the object
IndexError: If list/tuple index is out of range
AttributeError: If attribute does not exist on object
"""Parse path strings into machine-readable format for programmatic path manipulation.
def parse_path(path: str) -> List:
"""
Parse path string to machine-readable format.
Parameters:
- path: Path string in DeepDiff format (e.g., "root['key'][0]['subkey']")
Returns:
List of path components that can be used programmatically.
"""from deepdiff import extract, parse_path
# Simple nested dictionary
data = {
"user": {
"name": "John",
"age": 30,
"address": {
"street": "123 Main St",
"city": "New York"
}
}
}
# Extract nested values
name = extract(data, "root['user']['name']")
print(name) # "John"
city = extract(data, "root['user']['address']['city']")
print(city) # "New York"# Complex nested structure with lists
data = {
"users": [
{"id": 1, "name": "John", "roles": ["admin", "user"]},
{"id": 2, "name": "Jane", "roles": ["user"]}
],
"settings": {
"permissions": {
"admin": ["read", "write", "delete"],
"user": ["read"]
}
}
}
# Extract from list by index
first_user = extract(data, "root['users'][0]")
print(first_user) # {"id": 1, "name": "John", "roles": ["admin", "user"]}
# Extract nested list item
first_role = extract(data, "root['users'][0]['roles'][0]")
print(first_role) # "admin"
# Extract from nested dictionary
admin_permissions = extract(data, "root['settings']['permissions']['admin']")
print(admin_permissions) # ["read", "write", "delete"]# Parse path string to components
path_str = "root['users'][0]['name']"
path_components = parse_path(path_str)
print(path_components) # ['users', 0, 'name']
# Use parsed components with extract
name = extract(data, path_components)
print(name) # "John"
# Convert components back to string
from deepdiff.path import to_string
reconstructed = to_string(path_components)
print(reconstructed) # "root['users'][0]['name']"class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Company:
def __init__(self, name, employees):
self.name = name
self.employees = employees
# Create nested object structure
company = Company("TechCorp", [
Person("John", 30),
Person("Jane", 25)
])
# Extract from object attributes
company_name = extract(company, "root.name")
print(company_name) # "TechCorp"
first_employee_name = extract(company, "root.employees[0].name")
print(first_employee_name) # "John"# Handle missing paths gracefully
try:
missing_value = extract(data, "root['nonexistent']['key']")
except KeyError as e:
print(f"Path not found: {e}")
try:
out_of_bounds = extract(data, "root['users'][999]['name']")
except IndexError as e:
print(f"Index out of range: {e}")
# Safe extraction with default values
def safe_extract(obj, path, default=None):
try:
return extract(obj, path)
except (KeyError, IndexError, AttributeError):
return default
value = safe_extract(data, "root['missing']['key']", "default")
print(value) # "default"from deepdiff.path import GET, SET
# Use low-level path functions
path_components = ['users', 0, 'name']
# Get value using components
name = GET(data, path_components)
print(name) # "John"
# Set value using components (modifies original object)
SET(data, path_components, "Johnny")
updated_name = GET(data, path_components)
print(updated_name) # "Johnny"# Handle various path formats
data = {
"items": {
"item-1": {"value": 10},
"item_2": {"value": 20}
},
"list_items": [
{"key": "a", "value": 100},
{"key": "b", "value": 200}
]
}
# Extract with special characters in keys
value1 = extract(data, "root['items']['item-1']['value']")
print(value1) # 10
value2 = extract(data, "root['items']['item_2']['value']")
print(value2) # 20
# Find items by attribute value (requires custom logic)
def find_by_key(data, target_key):
for i, item in enumerate(data['list_items']):
if item['key'] == target_key:
return extract(data, f"root['list_items'][{i}]['value']")
return None
value_b = find_by_key(data, 'b')
print(value_b) # 200from deepdiff import DeepDiff
# Use extract with DeepDiff paths
original = {"user": {"name": "John", "age": 30}}
modified = {"user": {"name": "Jane", "age": 30}}
diff = DeepDiff(original, modified)
print(diff)
# Extract the paths that changed
if 'values_changed' in diff:
for path in diff['values_changed'].keys():
old_value = extract(original, path)
new_value = extract(modified, path)
print(f"Changed at {path}: {old_value} -> {new_value}")# Extract multiple values efficiently
paths_to_extract = [
"root['users'][0]['name']",
"root['users'][1]['name']",
"root['settings']['permissions']['admin'][0]"
]
extracted_values = {}
for path in paths_to_extract:
try:
extracted_values[path] = extract(data, path)
except (KeyError, IndexError, AttributeError) as e:
extracted_values[path] = f"Error: {e}"
for path, value in extracted_values.items():
print(f"{path}: {value}")# Path representation types
PathString = str # String format: "root['key'][0]['subkey']"
PathList = List[Union[str, int]] # Component format: ['key', 0, 'subkey']
PathComponent = Union[str, int] # Individual path component
# Extraction result types
ExtractedValue = Any # Any value that can be extracted
ExtractedPath = Union[PathString, PathList]
# Error types for path operations
class PathError(Exception):
"""Base exception for path operations."""
class PathNotFoundError(PathError, KeyError):
"""Exception raised when a path does not exist."""
class PathIndexError(PathError, IndexError):
"""Exception raised when a list/tuple index is invalid."""
class PathAttributeError(PathError, AttributeError):
"""Exception raised when an attribute does not exist."""Install with Tessl CLI
npx tessl i tessl/pypi-deepdiff