Registry / database / btrees

btrees

JSON →
library6.4pypypi✓ verified 90d ago

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 BTrees
INSTALL
IMPORT
SIG · BTREES
B
btrees
databasepythonv6.4
Install
2.8s avg
Import
168ms
Disk
28MB
Pass rate
5/ 10
Env Coverage5 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v6.4 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.920 runs
build_error
glibc
py 3.10–3.920 runs
installs and imports cleanly · install 2.8s · import 0.168s · 28MB
28MB installed
● package 28MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

OOBTree
✓ from BTrees.OOBTree import OOBTree
For B-trees with arbitrary Python objects as both keys and values.
IIBTree
✓ from BTrees.IIBTree import IIBTree
For B-trees with 32-bit signed integers as both keys and values. Optimized for performance and memory.
IOBTree
✓ from BTrees.IOBTree import IOBTree
For B-trees with 32-bit signed integers as keys and arbitrary Python objects as values.
OIBTree
✓ from BTrees.OIBTree import OIBTree
For B-trees with arbitrary Python objects as keys and 32-bit signed integers as values.

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.

from BTrees.OOBTree import OOBTree # Create an in-memory Object-Object BTree my_btree = OOBTree() # Insert key-value pairs (like a dictionary) my_btree['apple'] = 1 my_btree['banana'] = 2 my_btree['cherry'] = 3 my_btree['date'] = 4 print(f"BTree after insertions: {list(my_btree.items())}") # Access values by key print(f"Value for 'banana': {my_btree['banana']}") # Iterate over sorted keys print("Keys in sorted order:") for key in my_btree.keys(): print(key) # Check for key existence print(f"'apple' in btree: {'apple' in my_btree}") print(f"'grape' in btree: {'grape' in my_btree}") # Delete a key del my_btree['cherry'] print(f"BTree after deleting 'cherry': {list(my_btree.items())}") # Example of getting a value with a default value_or_default = my_btree.get('fig', 'default_value') print(f"Value for 'fig' (with default): {value_or_default}")
Debug
Known issues
breakingBTrees regularly drops support for older Python versions with new major/minor releases. Version 6.3 requires Python >=3.10. Older versions like 3.7, 3.8, and 3.9 are no longer supported by recent BTrees releases (e.g., 6.0 and 6.2).
fix
Ensure your Python environment is at least 3.10. Upgrade Python and BTrees to compatible versions.
affects: <6.3
gotchaWhen using custom objects as keys in BTrees (especially OOBTree) that are intended for persistence, ensure these objects implement proper comparison methods (`__lt__`, `__le__`, `__eq__`, `__hash__`). Python's default object comparison (by memory address) leads to non-deterministic order and problematic behavior upon deserialization if not handled correctly.
fix
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.
affects: All
gotchaThe BTrees library provides different modules for specific key/value types (e.g., `IIBTree` for integer keys/values, `OOBTree` for arbitrary objects). Mixing key/value types that do not match the chosen BTree variant (e.g., putting strings into an `IIBTree`) can lead to `TypeError` or other unexpected runtime issues.
fix
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.
affects: All
gotchaUnlike standard Python `dict.setdefault()`, the `BTrees.BTree.setdefault()` method requires a default value argument. It does not implicitly default to `None`.
fix
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.
affects: All
gotchaIn versions prior to 4.9.2, set-like operations (`union`, `intersection`, `difference`, `multiunion`) could produce incorrect results if input iterables were not pre-sorted. While newer versions automatically sort internally, for large datasets, providing pre-sorted iterables can still offer performance benefits.
fix
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.
affects: <4.9.2 (functionally fixed, but performance consideration remains)
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'btree'
Developers often search for a generic 'btree' package, but the widely used, optimized library is named 'BTrees' (plural and capitalized) and needs to be installed as such.
fix
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).
AttributeError: type object 'BTrees.OOBTree.OOBTree' has no attribute 'max_internal_size'
Attempting to directly set or access `max_internal_size` or `max_leaf_size` attributes on the C-optimized BTree classes (e.g., `OOBTree`) will raise an `AttributeError` or `TypeError` because these are built-in extension types whose attributes cannot be dynamically set in this manner.
fix
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 
```
TypeError: Object has default comparison
BTrees require keys to have a consistent and total ordering. If you use custom Python objects as keys without defining a `__lt__`, `__gt__`, or `__cmp__` method (for Python 2), `btrees` will fall back to default object comparison, which is based on memory address and is not stable across program runs or persistence, leading to this error.
fix
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'
```
RuntimeError: the bucket being iterated changed size
This error typically occurs when a BTree or one of its internal 'buckets' is modified (e.g., by adding or removing elements) while it is being iterated over. This violates the integrity of the iterator. It can also be a symptom of deeper data corruption.
fix
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
```
Upgrade
Version history
6.4latest on PyPI · released Apr 29, 2026
Audit
Dependencies
persistentrequiredUsed for object persistence, especially with ZODB integration.
zope.interfacerequiredUsed for interface definitions and adherence within the Zope ecosystem.
Agent activity
32 hits · last 30 days
node
28
Amazon
1
OpenAI (training)
1
Resources
btrees — pip install btrees · libregistry