https://github.com/likianta/hot-shelve
A wrapper for Python shelve to support updating nested dictionary in an elegant way.
https://github.com/likianta/hot-shelve
database nested-dictionary python python-shelve shelve
Last synced: 7 months ago
JSON representation
A wrapper for Python shelve to support updating nested dictionary in an elegant way.
- Host: GitHub
- URL: https://github.com/likianta/hot-shelve
- Owner: likianta
- Created: 2022-03-13T12:25:23.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2022-12-18T13:59:10.000Z (almost 3 years ago)
- Last Synced: 2025-03-08T22:16:57.674Z (8 months ago)
- Topics: database, nested-dictionary, python, python-shelve, shelve
- Language: Python
- Homepage:
- Size: 33.2 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Hot Shelve
A wrapper for Python shelve that supports updating nested dictionaries in a simple way.
Essentially, you don't need this any more:
```python
import shelve
db = shelve.open('some_file.db')
db['key'] = {'a': 1, 'b': 2}
temp = db['key']
temp['c'] = 3
db['key'] = temp
db.sync()
```
To use:
```python
import hot_shelve
db = hot_shelve.FlatShelve('some_file.db')
db['key'] = {'a': 1, 'b': 2}
db['key']['c'] = 3
db.sync()
```
## Basic Usages
```python
# hot_shelve provides `HotShelve` and `FlatShelve` classes.
# but currently (v0.1.0) only `FlatShelve` is available.
from hot_shelve import FlatShelve
# open a database
# ===============
# a database is a file with extension `.db`.
db = FlatShelve('path/to/db.db')
# add an immutable key-value pair
# ==============================
db['name'] = 'Bob'
# add a mutable key-value pair
# ============================
db['info'] = {'address': 'Tokyo'}
db['info']['phone_number'] = ['123-456-7890']
# print
# =====
# there are two ways to show its dict structure.
# 1. `db.to_dict()` shows user-oriented dict.
# 2. `db.to_internal_dict()` shows the real internal dict.
# ps: don't use `dict(db)`, it exposes mutable nodes with delegates, you can
# not see it clearly like `db.to_dict` does.
print(db.to_dict())
# -> {'name': 'Bob',
# 'info': {'address': 'Tokyo',
# 'phone_number': ['123-456-7890']}}
print(db.to_internal_dict())
# -> {'name': 'Bob',
# 'info.address': 'Tokyo',
# 'info.phone_number': ['123-456-7890']}
# delete a key
# ============
db.pop('name') # -> 'Bob'
db['info'].pop('address') # -> 'Tokyo'
print(db.to_dict())
# -> {'info': {'phone_number': ['123-456-7890']}}
# update a key
# ============
db['info']['phone_number'].append('987-654-3210')
print(db.to_dict())
# -> {'info': {'phone_number': ['123-456-7890',
# '987-654-3210']}}
# don't forget sync to disk
# =========================
db.sync() # now it's safely saved.
# you can do whatever like a Shelve object does
# =============================================
# get, keys, values, items, setdefault, pop, update, clear, sync, close, etc.
for k, v in db.items():
print(k, v) # -> 'info', {'phone_number': ['123-456-7890', '987-654-3210']}
db.setdefault('name', 'Alice') # -> 'Alice'
print(db.to_dict())
# -> {'name': 'Alice',
# 'info': {'phone_number': ['123-456-7890',
# '987-654-3210']}}
db.clear() # -> {}
...
db.close()
```
## Advanced Usages
```python
from hot_shelve import FlatShelve
db = FlatShelve('path/to/db.db')
db['info'] = {'address': 'Tokyo'}
# use `db['a.b.c']` instead of `db['a']['b']['c']`
db['info.phone_number'] = ['123-456-7890']
# it has the same effect as `db['info']['phone_number'] = ['123-456-7890']`.
```
## Tricks
Follow the instructions to get a (little) better performance (in theoretical).
1. `db['a.b.c']` is better than `db['a']['b']['c']`.
```python
# good
db['a']['b']['c'] = 'xxx'
# better
db['a.b.c'] = 'xxx'
```
2. To frequently update a node, assign it to a new variable.
```python
# good
db['a']['b']['0'] = '000'
db['a']['b']['1'] = '111'
db['a']['b']['2'] = '222'
...
# better
db['a.b.0'] = '000'
db['a.b.1'] = '111'
db['a.b.2'] = '222'
...
# best
node = db['a.b']
node['0'] = '000'
node['1'] = '111'
node['2'] = '222'
...
```
## Cautions
- Do not use '.' in your own key name, the period symbol is reserved for key chain derivation.
```
# wrong
words_db['splash'] = {
'e.g.': 'there was a splash, and then silence.'
}
''' it will generate...
print(words_db.to_dict())
# -> {'splash': {'e': {'g': {'': 'there was a splash, and then silence.'}}}}
print(words_db.to_internal_dict())
# -> {'splash.e.g.': 'there was a splash, and then silence.'}
'''
# right
words_db['splash'] = {
'example': 'there was a splash, and then silence.'
}
print(words_db.to_dict())
# -> {'splash': {'example': 'there was a splash, and then silence.'}}
print(words_db.to_internal_dict())
# -> {'splash.example': 'there was a splash, and then silence.'}
```
- The file size will be larger than `shelve.Shelve`, because it uses a flat key-value structure.
Illustration:
A normal `Shelve` object:
```yaml
data:
name: 'Bob'
info:
address: 'Tokyo'
phone_number:
- 123-456-7890
- 987-654-3210
```
A `FlatShelve` object:
```yaml
data.name: 'Bob'
data.info.address: 'Tokyo'
data.info.phone_number:
- 123-456-7890
- 987-654-3210
```