SimpSave is a lightweight Python key-value storage database for basic variable persistence, utilizing Python’s powerful built-in data structures. It follows a “read-and-use” style, making it extremely easy to use and perfect for small scripts such as student projects or configuration files.
SimpSave 10 is a major upgrade that introduces optional storage engines. With an encapsulated sqlite engine, it even reaches production usability levels for lightweight scenarios (despite having no connection pool mechanism for its functional API). For minimal environments, optional dependencies preserve the original zero-dependency ultra-lightweight nature.
- Extremely Lightweight: Minimal and efficient core code; dependency-free minimal installation
- Extremely Easy to Use: Functional APIs (
read(),write(), etc.) are straightforward with almost no learning curveimport simpsave as ss ss.write('key1', 'value1') ss.read('key1') # 'value1'
- Read-and-Use: Stored and retrieved types remain consistent, with no need for manual type conversion
import simpsave as ss ss.write('key1', 1) type(ss.read('key1')).__name__ # 'int' ss.read('key1') + 1 # 2
- Multi-Engine Support: From dependency-free lightweight
XMLengines to production-readySQLITEengines. SimpSave automatically selects an engine based on file extension—no configuration required.
SimpSave is available on PyPI. Install it using pip:
pip install simpsaveThen, import it into your project:
import simpsave as ss # commonly aliased as 'ss'And you’re ready to use it.
SimpSave supports optional dependencies so you can install only what you need:
pip install simpsave # Install with all engines
pip install simpsave[XML] # Minimal: XML engine only (requires xml.etree)
pip install simpsave[INI] # XML + INI engines (no external dependencies)
pip install simpsave[YML] # XML + YML engines (requires PyYAML)
pip install simpsave[TOML] # XML + TOML engines (requires tomli)
pip install simpsave[JSON] # XML + JSON engines (no external dependencies)
pip install simpsave[SQLITE] # XML + SQLITE engines (requires sqlite3)The
SQLITEengine requires an existing SQLite environment installed locally.
Below is a simple example to get started with SimpSave:
import simpsave as ss
# Write data
ss.write('name', 'Alice')
ss.write('age', 25)
ss.write('scores', [90, 85, 92])
# Read data
print(ss.read('name')) # Alice
print(ss.read('age')) # 25
print(ss.read('scores')) # [90, 85, 92]
# Check key existence
print(ss.has('name')) # True
print(ss.has('email')) # False
# Delete a key
ss.remove('age')
print(ss.has('age')) # False
# Regex match
ss.write('user_admin', True)
ss.write('user_guest', False)
print(ss.match(r'^user_')) # {'user_admin': True, 'user_guest': False}
# Use a different file (engine auto-selected)
ss.write('theme', 'dark', file='config.yml')
print(ss.read('theme', file='config.yml')) # dark
# Use :ss: mode (stored in installation directory)
ss.write('key1', 'value1', file=':ss:config.toml')
print(ss.read('key1', file=':ss:config.toml')) # value1
# Delete storage files
ss.delete()
ss.delete(file='config.yml')If you have basic programming knowledge, you’ll master SimpSave almost instantly.
SimpSave 10 supports multiple storage engines, selectable per use case. Each engine is defined in the ss.ENGINE enumeration:
| Engine | File Format | Dependency | Description |
|---|---|---|---|
XML |
.xml |
xml.etree (built-in) |
Stores data in XML format; lightweight, dependency-free |
INI |
.ini |
configparser (built-in) |
Stores data in INI format; limited Unicode support |
YML |
.yml |
PyYAML |
YAML format storage |
TOML |
.toml |
tomli |
TOML format storage |
JSON |
.json |
json (built-in) |
JSON format storage |
SQLITE |
.db |
sqlite3 (built-in) |
SQLite database; production-level performance |
SimpSave automatically chooses an engine based on the file extension provided to file:
import simpsave as ss
ss.write('key1', 'value1', file='data.yml') # Uses YML engine
ss.write('key2', 'value2', file='config.toml') # Uses TOML engine
ss.write('key3', 'value3', file='data.db') # Uses SQLITE engineSimpSave stores Python’s built-in basic data types as key-value pairs. The actual data format varies based on the selected engine.
By default, data is saved to
__ss__.xmlin the current working directory.
As in earlier versions, SimpSave supports the unique :ss: path prefix—files with :ss: (e.g., :ss:config.json) are stored in the SimpSave installation directory, ensuring cross-environment compatibility.
import simpsave as ss
ss.write('key1', 'value1', file=':ss:config.yml')
print(ss.read('key1', file=':ss:config.yml'))
:ss:mode is available only when SimpSave is installed viapip.
SimpSave fully supports Python’s basic built-in types, including:
intfloatstrboollist(including nested lists of basic types)dicttupleNone
When read back, data automatically restores to its original Python type—providing genuine “read-and-use” capability.
write writes a key-value pair into the specified file:
def write(key: str, value: any, *, file: str | None = None) -> bool:
...If the file doesn’t exist, it will be created automatically.
key: The key to save (string only)value: The value to store (any supported Python base type)file: Target file path; defaults to__ss__.xml. Supports:ss:mode. Engine is auto-selected by extension.
- Returns
Trueon success,Falseon failure.
ValueError: Value is not a supported Python base typeIOError: Write operation failedRuntimeError: Other runtime errors (e.g., engine not installed)
import simpsave as ss
ss.write('key1', 'Hello World')
ss.write('key2', 3.14)
ss.write('key3', [1, 2, 3, 'Text'])
ss.write('key4', {'a': 1, 'b': 2})
# Different engines
ss.write('config', 'value', file='settings.yml') # YML engine
ss.write('data', 100, file='cache.db') # SQLITE engineFiles are created automatically if missing.
read reads data from a specified file:
def read(key: str, *, file: str | None = None) -> any:
...key: Key name to readfile: File path to read from (defaults to__ss__.xml)
- Returns the value associated with the key (restored to its original type).
- Returns
Noneif the key does not exist.
IOError: Read errorRuntimeError: Engine error or missing dependency
import simpsave as ss
print(ss.read('key1'))
print(ss.read('key2'))
print(ss.read('key3'))
value = ss.read('config', file='settings.yml')has checks if a given key exists in the file:
def has(key: str, *, file: str | None = None) -> bool:
...key: Key name to checkfile: File path (defaults to__ss__.xml)
- Returns
Trueif the key exists, otherwiseFalse.
IOError: Read errorRuntimeError: Engine error
import simpsave as ss
print(ss.has('key1'))
print(ss.has('nonexistent'))remove deletes a key and its associated value:
def remove(key: str, *, file: str | None = None) -> bool:
...key: Key to deletefile: Target file (defaults to__ss__.xml)
- Returns
Trueon success,Falseon failure.
IOError: Write errorRuntimeError: Engine error
import simpsave as ss
ss.remove('key1')
print(ss.has('key1')) # Falsematch returns key-value pairs that match a regular expression:
def match(re: str = "", *, file: str | None = None) -> dict[str, any]:
...re: Regular expression string (empty = all keys)file: File path (defaults to__ss__.xml)
- Returns a dictionary of all matched key-value pairs.
IOError: Read errorRuntimeError: Engine error
import simpsave as ss
ss.write('user_name', 'Alice')
ss.write('user_age', 25)
ss.write('admin_name', 'Bob')
result = ss.match(r'^user_.*')
print(result)delete removes the entire storage file:
def delete(*, file: str | None = None) -> bool:
...file: File path to delete (defaults to__ss__.xml)
- Returns
Trueon success,Falseon failure.
IOError: Delete errorRuntimeError: Engine error
import simpsave as ss
ss.delete()
ss.delete(file='config.yml')SimpSave may raise the following exceptions. Understanding them helps you write more robust code.
Raised when attempting to store non-basic Python types.
Examples:
import simpsave as ss
class CustomClass:
pass
try:
ss.write('key1', CustomClass())
except ValueError as e:
print(f"Error: {e}")Raised when file read/write operations fail.
Examples:
import simpsave as ss
try:
ss.read('key1', file='/root/protected.db')
except IOError as e:
print(f"File I/O error: {e}")Raised for engine or runtime-related issues.
Examples:
import simpsave as ss
try:
ss.write('key1', 'value1', file='data.unknown')
except RuntimeError as e:
print(f"Runtime error: {e}")Use try-except to safely handle operations:
import simpsave as ss
# Safe write
try:
ss.write('key1', 'value1')
except ValueError as e:
print(f"Invalid value type: {e}")
except IOError as e:
print(f"Write failed: {e}")
except RuntimeError as e:
print(f"Runtime error: {e}")
# Safe read
try:
value = ss.read('key1')
if value is None:
print("Key does not exist")
except IOError as e:
print(f"Read failed: {e}")
except RuntimeError as e:
print(f"Runtime error: {e}")- For non-
SQLITEengines, keep data size and complexity under control. - Always use
has()ortry-exceptchecks before reading:import simpsave as ss value = 'default' if ss.has('key_1'): value = ss.read('key_1') else: ss.write('key_1', 'default')
- When file existence is uncertain, use initialization inside
try-except.
- When file existence is uncertain, use initialization inside
For more information, visit GitHub