Registry / database / persistent

persistent

JSON →
library6.7pypypi✓ verified 84d ago

The `persistent` library provides a base class, `Persistent`, for creating translucent persistent Python objects. These objects can track their their own 'dirty' state, indicating when they have been modified and need to be saved by an external persistence layer (e.g., ZODB). It is a fundamental component for building object persistence systems. The current version is 6.5, with major releases typically aligning with Python version support updates and addressing core behavior changes.

pip install persistent
INSTALL
IMPORT
SIG · PERSISTENT
P
persistent
databasepythonv6.7
Install
2.4s avg
Import
54ms
Disk
22MB
Pass rate
5/ 10
Env Coverage5 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v6.7 · 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.103.920 runs
build_error
glibc
py 3.103.920 runs
installs and imports cleanly · install 2.4s · import 0.054s · 24MB
22MB installed
● package 22MB
Code
Verified usage

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

Persistent
from persistent import Persistent

Demonstrates the basic usage of `persistent.Persistent` by subclassing it and observing how its `_p_changed` attribute is affected by direct attribute assignments. It also highlights a common gotcha regarding changes to mutable attributes within the object when not managed by a full persistence layer.

from persistent import Persistent class MyPersistentObject(Persistent): def __init__(self, name="Default"): self.name = name self.attributes = {} # A mutable dictionary def update_name(self, new_name): # Assigning to a direct attribute will mark the object dirty self.name = new_name def add_attribute(self, key, value): # For objects managed by a persistence layer (e.g., ZODB), # modifying this dict would also mark the parent dirty. # Without a persistence layer, direct dict modification here # does NOT automatically set _p_changed. self.attributes[key] = value def describe(self): return f"Name: {self.name}, Attributes: {self.attributes}" # Create an instance my_obj = MyPersistentObject("Initial Name") print(f"1. Initial state: {my_obj.describe()}, _p_changed: {my_obj._p_changed}") # Modifying a direct attribute marks it dirty my_obj.update_name("New Name 1") print(f"2. After update_name: {my_obj.describe()}, _p_changed: {my_obj._p_changed}") # Simulate 'saving' (a persistence layer would set _p_changed to None) my_obj._p_changed = None print(f"3. After 'saving': {my_obj.describe()}, _p_changed: {my_obj._p_changed}") # Modifying the mutable dictionary directly (without a storage proxy) # does NOT automatically set _p_changed, which is a common gotcha. my_obj.attributes['version'] = 1 print(f"4. After modifying internal dict: {my_obj.describe()}, _p_changed: {my_obj._p_changed}") # To ensure persistence layer detects changes in mutable objects, # you often need to manually set _p_changed or reassign the attribute # (e.g., obj.attributes = new_dict_or_copy) or rely on a proxy provided by the storage. my_obj._p_changed = True print(f"5. Manually set _p_changed after internal change: {my_obj.describe()}, _p_changed: {my_obj._p_changed}")
Debug
Known issues
breakingPython 2.7, 3.4, 3.5, and 3.6 support was dropped in `persistent` version 5.0. Python < 3.8 support was dropped in version 6.0.
fix
Upgrade to Python 3.8 or newer to use `persistent` 6.x. For older Python versions, pin `persistent` to an earlier major version (e.g., `persistent<5` for Python 2.7, `persistent<6` for Python 3.7).
affects: < 5.0, < 6.0
breakingThe `__dict__` attribute of `Persistent` objects no longer returns a `_PersistentDict` but a plain `dict`.
fix
Code that relied on `isinstance(obj.__dict__, _PersistentDict)` or specific `_PersistentDict` methods will break. Treat `obj.__dict__` as a standard Python dictionary.
affects: >= 6.0.0
gotchaThe `_p_changed` attribute is only automatically set to `True` for direct attribute assignments (e.g., `obj.attr = value`). Changes to mutable objects *inside* a `Persistent` object (e.g., `obj.my_list.append(item)`, `obj.my_dict[key] = value`) will NOT automatically mark the parent object as dirty if not managed by an active persistence layer that proxies these mutable objects. This is a common source of data loss if not handled correctly.
fix
Either reassign the mutable attribute (e.g., `obj.my_list = new_list`), manually set `obj._p_changed = True` after modifying the internal mutable object, or ensure the object is managed by a full persistence layer (like ZODB) that provides proxy objects for mutable attributes.
affects: All versions
gotchaThe `persistent` library provides the `Persistent` base class and change tracking mechanism, but it does NOT provide an object storage or database system itself. It is designed to be used in conjunction with a persistence layer like ZODB (Zope Object Database) to actually save and retrieve objects.
fix
Understand that `persistent` is a low-level building block. To persist objects to disk or a database, you will need to integrate it with a suitable persistence framework (e.g., ZODB).
affects: All versions
Errors
Common errors & fixes
ImportError: cannot import name 'Persistent'
This error often occurs due to historical changes in the `persistent` library's module structure or incorrect capitalization. Older tutorials or code might use `from persistence import Persistent` (incorrect module name) or attempt to import `persistence` instead of `Persistent` (incorrect class name).
fix
The correct way to import the `Persistent` class is `from persistent import Persistent` (lowercase `persistent` for the module, uppercase `Persistent` for the class).
TypeError: unhashable type: 'Persistent'
By default, instances of `Persistent` objects are unhashable because the class does not implement `__hash__` or `__eq__` methods. Python requires objects to be hashable to be used as keys in dictionaries or as elements in sets.
fix
If you need to use `Persistent` objects as dictionary keys or set members, you must implement `__hash__` and `__eq__` methods in your persistent class. Alternatively, avoid using `Persistent` objects directly in hash-based collections if identity-based comparisons are sufficient, as their object identity remains consistent across database connections.
AttributeError: 'Persistent' object has no attribute '_p_jar'
This error typically indicates that a `Persistent` object is being accessed or used outside the context of an active ZODB connection, which is responsible for managing the `_p_jar` attribute. It can also occur if the object's persistence state is corrupted or if a `persistent` class does not properly initialize this internal attribute.
fix
Ensure that `Persistent` objects are created, loaded, and manipulated within the scope of a ZODB database connection. If this error persists within a ZODB context, verify the health of your database and the lifecycle management of your persistent objects.
_pickle.UnpicklingError
This error indicates that Python's `pickle` module, used by the `persistent` library for object serialization, failed to deserialize an object. Common causes include corrupted data in the persistence layer, incompatibility between the `pickle` protocol versions used for saving and loading, or significant changes to class definitions that render old pickled data unreadable.
fix
Check for data corruption in your storage (e.g., ZODB data file). Ensure that the same Python and `persistent` library versions are used consistently for both saving and loading data. If class definitions have evolved, implement schema migration logic or `__setstate__`/`__getstate__` methods in your persistent classes to handle backward compatibility. Verify the `pickle` protocol version in use, especially when migrating between older and newer Python/ZODB versions.
Upgrade
Version history
6.7latest on PyPI · released May 26, 2026
Audit
Dependencies

No dependency data recorded yet.

Agent activity
14 hits · last 30 days
node
14
Resources
persistent — pip install persistent · libregistry