dpath: Filesystem-like Pathing for Dictionaries
dpath-python provides filesystem-like pathing and searching capabilities for nested dictionary and list structures. It allows you to get, set, delete, and search data within complex Python objects using a simple string path syntax. The current version is 2.2.0, and the library maintains an active release cadence with regular updates and bug fixes.
Common errors
-
KeyError: 'path/to/missing/key'
cause The specified path or a segment of the path (glob) does not exist within the dictionary structure, causing dpath to fail when trying to access a non-existent key.fixUse `dpath.get(obj, path, default=None)` to provide a default value if the path is not found, or verify the path's existence using `dpath.search()` before attempting to retrieve its value. -
ModuleNotFoundError: No module named 'dpath.util'
cause The `dpath.util` package has been deprecated, and its functions have been moved directly to the top-level `dpath` package.fixImport functions directly from the `dpath` package instead of `dpath.util`. For example, change `import dpath.util` to `import dpath` and use `dpath.get()` instead of `dpath.util.get()`. -
TypeError: 'int' object is not subscriptable
cause This error occurs when `dpath.new()` or `dpath.set()` attempts to create or modify nested path entries inside an object that is not a dictionary or a list (e.g., an integer or a string), which cannot be subscripted.fixEnsure that the parent nodes in the path you are trying to create or modify are mutable collection types (dictionaries or lists) that can hold further nested structures. Initialize intermediate paths with appropriate dictionary or list types if they don't exist, or use `dpath.new()` with `creator=dict` or `creator=list` for specific nodes. -
ValueError: More than one leaf matched the glob
cause `dpath.get()` is designed to retrieve a single, unambiguous value. This error is raised when the provided glob pattern matches multiple elements in the dictionary, preventing a unique result.fixRefine the glob pattern to be more specific to ensure it matches only one element. If multiple matches are intended, use `dpath.search()` or `dpath.values()` which are designed to return multiple results.
Warnings
- breaking dpath dropped support for Python 2.x. Any projects relying on older Python versions will need to upgrade to Python 3.7+.
- breaking Behavior for interpreting integer-like path segments when creating new paths was changed to resolve ambiguity. This may lead to dictionary keys being created (e.g., `{'0': ...}`) instead of list indices (e.g., `[..., ...]`) if the target path is not an existing list or explicitly initialized as one.
- gotcha `dpath.values()` and `dpath.search()` return generators, not immediate lists. If you expect a list, you must explicitly convert the generator.
- gotcha The `dpath.merge()` function's default behavior can replace entire lists or dictionaries. For more granular control over merging, especially for lists, the `merge_types` parameter should be used.
- gotcha `dpath.get()` raises `KeyError` when a path does not exist, by default. Users expecting behavior similar to Python's `dict.get()` (which returns `None` for missing keys) might encounter unexpected `KeyError`s.
- gotcha `dpath.get()` raises a `KeyError` if the specified path does not exist. Unlike `dict.get()`, it does not accept a default value to return for missing paths.
Install
-
pip install dpath
Imports
- dpath
import dpath
Quickstart
import dpath
# Sample data
data = {
"user": {
"profile": {
"name": "Alice",
"age": 30,
"interests": ["coding", "photography"]
},
"settings": {
"theme": "dark"
}
},
"items": [
{"id": 1, "name": "itemA"},
{"id": 2, "name": "itemB"}
]
}
print("Original data:")
print(data)
print("-" * 20)
# Get a value
name = dpath.get(data, '/user/profile/name')
print(f"User name: {name}")
# Set a value (creates path if it doesn't exist)
dpath.set(data, '/user/profile/age', 31)
print(f"Updated age: {dpath.get(data, '/user/profile/age')}")
dpath.set(data, '/user/profile/city', 'New York')
print(f"Added city: {dpath.get(data, '/user/profile/city')}")
# Get all values matching a pattern (returns a generator)
print("\nAll item names:")
for item_name in dpath.values(data, '/items/*/name'):
print(f"- {item_name}")
# Merge data (default is to update/replace)
new_settings = {"user": {"settings": {"notifications": True}}}
dpath.merge(data, new_settings)
print("\nData after merge:")
print(data)
# Delete a path
dpath.delete(data, '/user/settings/notifications')
print("\nData after deleting notifications:")
print(data)