{"id":6325,"library":"btrees","title":"BTrees","description":"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.","status":"active","version":"6.3","language":"python","source_language":"en","source_url":"https://github.com/zopefoundation/BTrees","tags":["data structure","persistence","B-tree","ZODB","mapping"],"install":[{"cmd":"pip install BTrees","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Used for object persistence, especially with ZODB integration.","package":"persistent","optional":false},{"reason":"Used for interface definitions and adherence within the Zope ecosystem.","package":"zope.interface","optional":false}],"imports":[{"note":"For B-trees with arbitrary Python objects as both keys and values.","symbol":"OOBTree","correct":"from BTrees.OOBTree import OOBTree"},{"note":"For B-trees with 32-bit signed integers as both keys and values. Optimized for performance and memory.","symbol":"IIBTree","correct":"from BTrees.IIBTree import IIBTree"},{"note":"For B-trees with 32-bit signed integers as keys and arbitrary Python objects as values.","symbol":"IOBTree","correct":"from BTrees.IOBTree import IOBTree"},{"note":"For B-trees with arbitrary Python objects as keys and 32-bit signed integers as values.","symbol":"OIBTree","correct":"from BTrees.OIBTree import OIBTree"}],"quickstart":{"code":"from BTrees.OOBTree import OOBTree\n\n# Create an in-memory Object-Object BTree\nmy_btree = OOBTree()\n\n# Insert key-value pairs (like a dictionary)\nmy_btree['apple'] = 1\nmy_btree['banana'] = 2\nmy_btree['cherry'] = 3\nmy_btree['date'] = 4\n\nprint(f\"BTree after insertions: {list(my_btree.items())}\")\n\n# Access values by key\nprint(f\"Value for 'banana': {my_btree['banana']}\")\n\n# Iterate over sorted keys\nprint(\"Keys in sorted order:\")\nfor key in my_btree.keys():\n    print(key)\n\n# Check for key existence\nprint(f\"'apple' in btree: {'apple' in my_btree}\")\nprint(f\"'grape' in btree: {'grape' in my_btree}\")\n\n# Delete a key\ndel my_btree['cherry']\nprint(f\"BTree after deleting 'cherry': {list(my_btree.items())}\")\n\n# Example of getting a value with a default\nvalue_or_default = my_btree.get('fig', 'default_value')\nprint(f\"Value for 'fig' (with default): {value_or_default}\")","lang":"python","description":"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."},"warnings":[{"fix":"Ensure your Python environment is at least 3.10. Upgrade Python and BTrees to compatible versions.","message":"BTrees 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).","severity":"breaking","affected_versions":"<6.3"},{"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.","message":"When 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.","severity":"gotcha","affected_versions":"All"},{"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.","message":"The 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.","severity":"gotcha","affected_versions":"All"},{"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.","message":"Unlike standard Python `dict.setdefault()`, the `BTrees.BTree.setdefault()` method requires a default value argument. It does not implicitly default to `None`.","severity":"gotcha","affected_versions":"All"},{"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.","message":"In 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.","severity":"gotcha","affected_versions":"<4.9.2 (functionally fixed, but performance consideration remains)"}],"env_vars":null,"search_vec":"'16':58 '2025':59 '6.3':54 'activ':62 'align':66 'around':17 'b':75 'b-tree':74 'btree':1,2,20 'built':16 'cadenc':64 'concurr':33 'contain':15 'current':51 'data':21,71 'effici':36 'heavili':25 'larg':41 'load':45 'map':42,78 'memori':49 'modifi':19 'node':47 'novemb':57 'object':14 'offer':35 'often':65 'optim':26 'optimist':32 'packag':6 'paradigm':34 'persist':13,73 'provid':8 'python':5,68 'releas':55,63 'relev':46 'retriev':39 'scalabl':12 'set':10 'storag':37 'structur':22,72 'support':70 'tree':76 'use':28 'version':52,69 'within':29 'zodb':30,77","created_at":"2026-04-15T05:32:24.371310+00:00","updated_at":"2026-04-16T01:03:53.802323+00:00","problems":[{"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).","cause":"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.","error":"ModuleNotFoundError: No module named 'btree'"},{"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.\n```python\n# Recommended way to customize node sizes\nimport BTrees.OOBTree\n\nclass MyCustomBTree(BTrees.OOBTree.BTree):\n    max_leaf_size = 500\n    max_internal_size = 1000\n\nmy_tree = MyCustomBTree()\n```\nOr, if the version supports it and you intend to modify global defaults (check documentation for specific version behavior):\n```python\n# This might work in newer versions for C extensions or pure-Python implementations\nimport BTrees.OOBTree\nBTrees.OOBTree.BTree.max_internal_size = 1000 \n```","cause":"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.","error":"AttributeError: type object 'BTrees.OOBTree.OOBTree' has no attribute 'max_internal_size'"},{"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.\n```python\nimport BTrees.OOBTree\n\nclass MySortableObject:\n    def __init__(self, value):\n        self.value = value\n\n    def __lt__(self, other):\n        if isinstance(other, MySortableObject):\n            return self.value < other.value\n        return NotImplemented\n\n    def __eq__(self, other):\n        if isinstance(other, MySortableObject):\n            return self.value == other.value\n        return NotImplemented\n\n    def __hash__(self):\n        return hash(self.value) # Required if objects are also used in sets/dicts\n\nbt = BTrees.OOBTree.BTree()\nbt[MySortableObject(1)] = 'one'\nbt[MySortableObject(2)] = 'two'\n```","cause":"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.","error":"TypeError: Object has default comparison"},{"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.\n```python\nimport BTrees.OOBTree\n\nbt = BTrees.OOBTree.BTree()\nbt['a'] = 1\nbt['b'] = 2\nbt['c'] = 3\n\n# INCORRECT (will raise RuntimeError if 'd' is added while iterating)\n# for key in bt.keys():\n#     if key == 'b':\n#         bt['d'] = 4\n\n# CORRECT way to modify during 'iteration' logically\nkeys_to_process = list(bt.keys())\nfor key in keys_to_process:\n    if key == 'b':\n        bt['d'] = 4\n\n# If corruption is suspected:\n# from BTrees.check import check, display\n# check(bt) # Raises AssertionError on consistency issues\n# display(bt) # Prints internal structure for manual inspection\n```","cause":"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.","error":"RuntimeError: the bucket being iterated changed size"}],"ecosystem":"pypi","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":"6.4","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/zopefoundation/BTrees","docs":"https://btrees.readthedocs.io","changelog":"https://github.com/zopefoundation/BTrees/blob/master/CHANGES.rst","pypi":"https://pypi.org/project/btrees/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["database","serialization"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-28","last_verified":"2026-06-28","next_check":"2026-07-28","install_tag":null}}