pyscript.storage
This module wraps the browser's IndexedDB persistent storage to provide a familiar Python dictionary API. Data is automatically serialized and persisted, surviving page reloads and browser restarts.
Storage is persistent per origin (domain), isolated between different sites for security. Browsers typically allow each origin to store up to 10-60% of total disk space, depending on browser and configuration.
What this module provides:
- A
dict-like API (get, set, delete, iterate). - Automatic serialization of common Python types.
- Background persistence with optional explicit
sync(). - Support for custom
Storagesubclasses.
from pyscript import storage
# Create or open a named storage.
my_data = await storage("user-preferences")
# Use like a regular dictionary.
my_data["theme"] = "dark"
my_data["font_size"] = 14
my_data["settings"] = {"notifications": True, "sound": False}
# Changes are queued automatically.
# To ensure immediate write, sync explicitly.
await my_data.sync()
# Read values (survives page reload).
theme = my_data.get("theme", "light")
Common types are automatically serialized: bool, int, float, str, None,
list, dict, tuple. Binary data (bytearray, memoryview) can be stored as
single values but not nested in structures.
Tuples are deserialized as lists due to IndexedDB limitations.
Info
Browsers typically allow 10-60% of total disk space per origin. Chrome and Edge allow up to 60%, Firefox up to 10 GiB (or 10% of disk, whichever is smaller). Safari varies by app type. These limits are unlikely to be reached in typical usage.
Storage
Bases: dict
A persistent dictionary backed by the browser's IndexedDB.
This class provides a dict-like interface with automatic persistence.
Changes are queued for background writing, with optional explicit
synchronization via sync().
Inherits from dict, so all standard dictionary methods work as expected.
from pyscript import storage
# Open a storage.
prefs = await storage("preferences")
# Use as a dictionary.
prefs["color"] = "blue"
prefs["count"] = 42
# Iterate like a dict.
for key, value in prefs.items():
print(f"{key}: {value}")
# Ensure writes complete immediately.
await prefs.sync()
Sometimes you may need to subclass Storage to add custom behavior:
from pyscript import storage, Storage, window
class LoggingStorage(Storage):
def __setitem__(self, key, value):
window.console.log(f"Setting {key} = {value}")
super().__setitem__(key, value)
my_store = await storage("app-data", storage_class=LoggingStorage)
my_store["test"] = 123 # Logs to console.
Source code in pyscript/storage.py
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | |
__init__(store)
Create a Storage instance wrapping an IndexedDB store (a JS
proxy).
__delitem__(key)
Delete an item from storage via its key.
The deletion is queued for persistence. Use sync() to ensure
immediate completion.
__setitem__(key, value)
Set a key to a value in storage.
The change is queued for persistence. Use sync() to ensure
immediate completion. The value must be a supported type for
serialization.
Source code in pyscript/storage.py
clear()
Remove all items from storage.
The clear() operation is queued for persistence. Use sync() to ensure
immediate completion.
sync()
async
Force immediate synchronization to IndexedDB.
By default, storage operations are queued and written asynchronously.
Call sync() when you need to guarantee changes are persisted immediately,
such as before critical operations or page unload.
store = await storage("important-data")
store["critical_value"] = data
# Ensure it's written before proceeding.
await store.sync()
This is a blocking operation that waits for IndexedDB to complete the write.
Source code in pyscript/storage.py
storage(name='', storage_class=Storage)
async
Open or create persistent storage with a unique name and optional
storage_class (used to extend the default Storage based behavior).
Each storage is isolated by name within the current origin (domain). If the storage doesn't exist, it will be created. If it does exist, its current contents will be loaded.
This function returns a Storage instance (or custom subclass instance)
acting as a persistent dictionary. A ValueError is raised if name is
empty or not provided.
from pyscript import storage
# Basic usage.
user_data = await storage("user-profile")
user_data["name"] = "Alice"
user_data["age"] = 30
# Multiple independent storages.
settings = await storage("app-settings")
cache = await storage("api-cache")
# With custom Storage class.
class ValidatingStorage(Storage):
def __setitem__(self, key, value):
if not isinstance(key, str):
raise TypeError("Keys must be strings")
super().__setitem__(key, value)
validated = await storage("validated-data", ValidatingStorage)
Storage names are automatically prefixed with "@pyscript/" to
namespace them within IndexedDB.