Skip to main content

A lightweight Python SQLite key-value store built on sqlite3.

Project description

TinyKV: Python SQLite key-value store

TinyKV is a lightweight Python SQLite key-value store built on top of the sqlite3 module from the standard library. It provides a small key-value database API for Python applications that need persistent local storage without external dependencies.

Use TinyKV when you want an embedded SQLite-backed key-value database for configuration data, local caches, application state, or small metadata stores.

TinyKV requires Python 3.11 or above.

Why TinyKV?

  • Python key-value store backed by SQLite
  • Uses the standard library sqlite3 module
  • Works with in-memory and file-based SQLite databases
  • Stores strings, numbers, bytes, and other Python objects
  • Keeps connection and transaction control with the caller

Installation

pip install tinykv

Quick start

First let’s import sqlite3 and the TinyKV module:

>>> import sqlite3
>>> import tinykv

TinyKV does not create a SQLite database connection for you. Instead, it operates on connections managed by the caller. So let’s create a database to use in the examples:

>>> conn = sqlite3.connect(':memory:')

This is how you create a TinyKV object:

>>> kv = tinykv.TinyKV(conn, allow_pickle=True)
Traceback (most recent call last):
    ...
RuntimeError: Table 'kv' not found in the database

Oops... TinyKV does not create the database table it needs either. For that the application can use create_schema():

>>> tinykv.create_schema(conn)

Let’s try again:

>>> kv = tinykv.TinyKV(conn, allow_pickle=True)
>>> kv  # doctest: +ELLIPSIS
<tinykv.TinyKV object at 0x...>

Now it works!

By default, TinyKV currently allows pickle-based value serialization/deserialization for compatibility. If allow_pickle is omitted, TinyKV currently behaves as if allow_pickle=True and emits a FutureWarning. Applications should not rely on this behavior and should explicitly set allow_pickle=False when handling databases that might be untrusted. The default is expected to change to False in a future release.

Storing and retrieving data

Use set() and get() to store and retrieve data from a TinyKV database, respectively:

>>> kv.set('foo', 'bar')
>>> kv.get('foo')
'bar'

Trying to get a nonexistent key raises KeyError:

>>> kv.get('not-there')
Traceback (most recent call last):
    ...
KeyError: 'not-there'

You can pass a default value to be returned if a key does not exist:

>>> kv.get('not-there', 'but-try-this')
'but-try-this'

Value data types

You can store any regular Python scalar in the key-value database:

>>> kv.set('foo', None)
>>> foo = kv.get('foo')
>>> foo is None
True

>>> kv.set('one', 1)
>>> kv.get('one')
1

>>> kv.set('pi', 3.1415926)
>>> kv.get('pi')
3.1415926

>>> kv.set('nan', float('nan'))
>>> import math
>>> math.isnan(kv.get('nan'))
True

Same for container objects:

>>> kv.set('a_list', ['one', 'two', 'three'])
>>> kv.get('a_list')
['one', 'two', 'three']

In fact, you can store any pickable object when allow_pickle=True (the current default):

>>> import datetime
>>>
>>> kv.set('a-long-time-ago', datetime.datetime(2022, 3, 19, 20, 15, 5))

>>> a_long_time_ago = kv.get('a-long-time-ago')

>>> a_long_time_ago
datetime.datetime(2022, 3, 19, 20, 15, 5)

>>> type(a_long_time_ago)
<class 'datetime.datetime'>

For safer behavior with untrusted database contents, disable pickle:

>>> safe_kv = tinykv.TinyKV(conn, allow_pickle=False)

Removing entries

Use remove() to remove entries from the database:

>>> kv.set('foo', 'bar')
>>> kv.remove('foo')
>>> kv.get('foo')
Traceback (most recent call last):
    ...
KeyError: 'foo'

Working with multiple entries

Use set_many() with a key-value dict to store multiple entries at once:

>>> kv.set_many({
...     'one': 1,
...     'two': 2,
... })
>>> kv.get('one')
1
>>> kv.get('two')
2

Call get_many() to retrieve many entries. The function returns a dict of all keys-values found in the database:

>>> kv.set('one', 1)
>>> kv.set('two', 2)
>>> kv.get_many(['one', 'two', 'not-there'])
{'one': 1, 'two': 2}

You can also use get_glob() to fetch entries based a glob pattern:

>>> kv.set('foo:abc', 1)
>>> kv.set('foo:xyz', 2)
>>> kv.set('bar:123', 3)

>>> kv.get_glob('foo:*')
{'foo:abc': 1, 'foo:xyz': 2}

>>> kv.get_glob('*:123')
{'bar:123': 3}

Notice that get_many() and get_glob() never raise KeyError for nonexistent keys. Instead, those keys are simply not present in the returned dict.

You can also remove many entries in one call with remove_many(). Nonexistent keys are silently ignored.

>>> kv.get('one')
1

>>> kv.remove_many(['one', 'not-there'])
>>> kv.get('one')
Traceback (most recent call last):
    ...
KeyError: 'one'

Using glob patterns

Use get_glob() to fetch entries using a shell-like wildcard pattern from the SQLite key-value store:

The pattern uses SQLite's GLOB syntax: * matches any sequence of characters, and ? matches a single character. Note that patterns are case-sensitive and use literal character matching (not regex).

Database setup

TinyKV requires the database table to exist before use. Create it with create_schema():

>>> import sqlite3
>>> conn = sqlite3.connect(':memory:')
>>> tinykv.create_schema(conn)

If you need idempotent setup, pass if_not_exists=True:

>>> tinykv.create_schema(conn, if_not_exists=True)

You can use a custom table name:

>>> tinykv.create_schema(conn, table='my_keys')

See the Miscellaneous section for table name requirements.

Use cases

TinyKV is a good fit when you need a Python SQLite key-value store for:

  • application configuration and settings
  • local cache data
  • lightweight metadata storage
  • persistent state for command-line tools
  • embedded storage in desktop scripts or services

Miscellaneous

  • TinyKV keys must be non-empty string scalars. Non-string keys raise TypeError, and empty strings raise ValueError. Keys are case-sensitive (since v0.1.4).

  • TinyKV does not open or manage transactions. Also, it operates both in autocommit and non-autocommit mode. All operations are atomic.

  • Naturally, if the connection handle is not in autocommit mode, you must call commit() on the connection to save the data.

  • The connection handle is available in the read-only attribute conn of the TinyKV object:

      >>> kv.conn  # doctest: +ELLIPSIS
      <sqlite3.Connection object at 0x...>
    
  • By default the table used by TinyKV is called kv. You can change that by passing a table argument to create_schema() and the TinyKV constructor:

      >>> CUSTOM_TABLE = 'custom_kv'
      >>>
      >>> tinykv.create_schema(conn, table=CUSTOM_TABLE)
      >>>
      >>> custom_kv = tinykv.TinyKV(
      ...     conn,
      ...     table=CUSTOM_TABLE,
      ...     allow_pickle=True,
      ... )
    

    Table names must match the pattern [a-zA-Z_][a-zA-Z0-9_]*. Invalid names raise ValueError.

Questions? Bugs? Suggestions?

Visit https://github.com/flaviovs/tinykv

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tinykv-0.2.1.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tinykv-0.2.1-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file tinykv-0.2.1.tar.gz.

File metadata

  • Download URL: tinykv-0.2.1.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.5

File hashes

Hashes for tinykv-0.2.1.tar.gz
Algorithm Hash digest
SHA256 946e2705534a96bea9d73f7af0a06a2a9807fb250bc08070e0d6c237c6355123
MD5 0b8514fb15ef89cb18eb31a417d21a45
BLAKE2b-256 4aa087610bf808ee5f662e1346e0227dfd0f90036b1f8a78a19cbcadb9f2498d

See more details on using hashes here.

File details

Details for the file tinykv-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: tinykv-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 8.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.32.5

File hashes

Hashes for tinykv-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 deda2f02f97c65bce30417f478b6a009b602fd30778cc97418034f690560b53d
MD5 86e247b1f247d5029c88290a0191b5de
BLAKE2b-256 48278d8a01d4d4bc72961ebff20bfa192e354964a25ea2843282d8be9e1636d9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page