BTrees is a Python package that provides a set of scalable, persistent object containers built around a modified BTree data structure. It is heavily optimized for use within ZODB's "optimistic concurrency" paradigm, offering efficient storage and retrieval of large mappings by only loading relevant nodes into memory. The current version is 6.3, released on November 16, 2025, with an active release cadence, often aligning with Python version support.
pip install BTreesVerified import paths — ran on the pinned version, not inferred.
This quickstart demonstrates basic usage of an OOBTree (Object-Object BTree), including creation, insertion, access, iteration, existence checks, and deletion. BTrees behave largely like standard Python dictionaries but are optimized for persistence and large datasets.
Ensure your Python environment is at least 3.10. Upgrade Python and BTrees to compatible versions.
Define `__lt__` (or a full rich comparison set) and `__hash__` methods on your custom key objects to ensure stable and meaningful ordering for BTree operations.
Always import and use the BTree variant that matches the types of keys and values you intend to store. For example, `IIBTree` for integers, `OOBTree` for arbitrary objects, `IOBTree` for integer keys and object values.
Always provide a second argument (the default value) to `setdefault()`, e.g., `my_btree.setdefault('missing_key', 'default_value')`. This is because some BTree types (like `IIBTree`) cannot store `None` as a value.For optimal performance, especially with large inputs, pre-sort any iterables passed to BTree set operations. If not pre-sorted, be aware of the potential performance overhead for internal sorting.
Ensure you install the correct package and import from it: `pip install BTrees` followed by `from BTrees.OOBTree import OOBTree` (or other specific BTree types).
To customize node sizes, you should subclass the BTree type and set `max_internal_size` and `max_leaf_size` within the subclass definition. Alternatively, in `btrees` versions 4.9.0 and later, you can modify these attributes directly on the class if using the pure Python implementation or via a specific mechanism if using the C extension.
```python
# Recommended way to customize node sizes
import BTrees.OOBTree
class MyCustomBTree(BTrees.OOBTree.BTree):
max_leaf_size = 500
max_internal_size = 1000
my_tree = MyCustomBTree()
```
Or, if the version supports it and you intend to modify global defaults (check documentation for specific version behavior):
```python
# This might work in newer versions for C extensions or pure-Python implementations
import BTrees.OOBTree
BTrees.OOBTree.BTree.max_internal_size = 1000
```Ensure that any custom object used as a key in a BTree implements a reliable comparison method, such as `__lt__` (less than) to provide a total ordering. For persistent objects in ZODB, avoid using `Persistent` objects as keys directly without careful consideration of their comparison behavior.
```python
import BTrees.OOBTree
class MySortableObject:
def __init__(self, value):
self.value = value
def __lt__(self, other):
if isinstance(other, MySortableObject):
return self.value < other.value
return NotImplemented
def __eq__(self, other):
if isinstance(other, MySortableObject):
return self.value == other.value
return NotImplemented
def __hash__(self):
return hash(self.value) # Required if objects are also used in sets/dicts
bt = BTrees.OOBTree.BTree()
bt[MySortableObject(1)] = 'one'
bt[MySortableObject(2)] = 'two'
```Avoid modifying a BTree (or any of its constituent parts) during iteration. If modifications are necessary, collect the keys to be modified/deleted beforehand and then perform the operations in a separate loop after the iteration, or create a copy of the keys/items to iterate over. If the error persists without explicit concurrent modification, it may indicate data corruption, potentially requiring diagnostic tools like `BTrees.check.check()` or database recovery procedures if used with ZODB.
```python
import BTrees.OOBTree
bt = BTrees.OOBTree.BTree()
bt['a'] = 1
bt['b'] = 2
bt['c'] = 3
# INCORRECT (will raise RuntimeError if 'd' is added while iterating)
# for key in bt.keys():
# if key == 'b':
# bt['d'] = 4
# CORRECT way to modify during 'iteration' logically
keys_to_process = list(bt.keys())
for key in keys_to_process:
if key == 'b':
bt['d'] = 4
# If corruption is suspected:
# from BTrees.check import check, display
# check(bt) # Raises AssertionError on consistency issues
# display(bt) # Prints internal structure for manual inspection
```