Python中的持久化字典,由sqlite3和pickle支持,线程安全。
项目描述
Python的sqlite3数据库的轻量级包装,具有简单、Pythonic的类似字典的接口和多线程访问支持。
用法
写入
>>> from sqlitedict import SqliteDict
>>> db = SqliteDict("example.sqlite")
>>>
>>> db["1"] = {"name": "first item"}
>>> db["2"] = {"name": "second item"}
>>> db["3"] = {"name": "yet another item"}
>>>
>>> # Commit to save the objects.
>>> db.commit()
>>>
>>> db["4"] = {"name": "yet another item"}
>>> # Oops, forgot to commit here, that object will never be saved.
>>> # Always remember to commit, or enable autocommit with SqliteDict("example.sqlite", autocommit=True)
>>> # Autocommit is off by default for performance.
>>>
>>> db.close()
读取
>>> from sqlitedict import SqliteDict
>>> db = SqliteDict("example.sqlite")
>>>
>>> print("There are %d items in the database" % len(db))
There are 3 items in the database
>>>
>>> # Standard dict interface. items() values() keys() etc...
>>> for key, item in db.items():
... print("%s=%s" % (key, item))
1={'name': 'first item'}
2={'name': 'second item'}
3={'name': 'yet another item'}
>>>
>>> db.close()
效率
默认情况下,sqlitedict的异常处理优先考虑详细性而不是效率。它从错误日志中提取和输出外层异常堆栈。如果您更倾向于效率,那么请用outer_stack=False初始化DB。
>>> from sqlitedict import SqliteDict
>>> db = SqliteDict("example.sqlite", outer_stack=False) # True is the default
>>> db[1]
{'name': 'first item'}
上下文管理器
>>> from sqlitedict import SqliteDict
>>>
>>> # The database is automatically closed when leaving the with section.
>>> # Uncommitted objects are not saved on close. REMEMBER TO COMMIT!
>>>
>>> with SqliteDict("example.sqlite") as db:
... print("There are %d items in the database" % len(db))
There are 3 items in the database
表
数据库文件可以存储多个表。如果没有指定表名,则使用默认表。
注意:写入是序列化的,拥有多个表不会提高性能。
>>> from sqlitedict import SqliteDict
>>>
>>> products = SqliteDict("example.sqlite", tablename="product", autocommit=True)
>>> manufacturers = SqliteDict("example.sqlite", tablename="manufacturer", autocommit=True)
>>>
>>> products["1"] = {"name": "first item", "manufacturer_id": "1"}
>>> products["2"] = {"name": "second item", "manufacturer_id": "1"}
>>>
>>> manufacturers["1"] = {"manufacturer_name": "afactory", "location": "US"}
>>> manufacturers["2"] = {"manufacturer_name": "anotherfactory", "location": "UK"}
>>>
>>> tables = products.get_tablenames('example.sqlite')
>>> print(tables)
['unnamed', 'product', 'manufacturer']
>>>
>>> products.close()
>>> manufacturers.close()
如果您想知道,未命名的表来自之前的示例,其中我们没有指定表名。
序列化
键是字符串。值是任何可序列化对象。
默认情况下,内部使用Pickle来(反)序列化值。
可以使用自定义(反)序列化器,特别是用于JSON和压缩。
>>> # Use JSON instead of pickle
>>> import json
>>> with SqliteDict("example.sqlite", encode=json.dumps, decode=json.loads) as mydict:
... pass
>>>
>>> # Apply zlib compression after pickling
>>> import zlib, pickle, sqlite3
>>>
>>> def my_encode(obj):
... return sqlite3.Binary(zlib.compress(pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)))
>>>
>>> def my_decode(obj):
... return pickle.loads(zlib.decompress(bytes(obj)))
>>>
>>> with SqliteDict("example.sqlite", encode=my_encode, decode=my_decode) as mydict:
... pass
还可以使用自定义(反)序列化器来允许非字符串键。
>>> # Use key encoding instead of default string keys only
>>> from sqlitedict import encode_key, decode_key
>>> with SqliteDict("example.sqlite", encode_key=encode_key, decode_key=decode_key) as mydict:
... pass
更多
函数有良好的文档,直接在 sqlitedict.py 中的docstrings中查看,或调用 help(sqlitedict)。
注意:由于Python语义,sqlitedict 无法知道内存中基于SqliteDict的条目何时被修改。您需要显式地将修改后的对象分配回SqliteDict
>>> from sqlitedict import SqliteDict
>>> db = SqliteDict("example.sqlite")
>>> db["colors"] = {"red": (255, 0, 0)}
>>> db.commit()
>>>
>>> colors = db["colors"]
>>> colors["blue"] = (0, 0, 255) # sqlite DB not updated here!
>>> db["colors"] = colors # now updated
>>>
>>> db.commit() # remember to commit (or set autocommit)
>>> db.close()
特性
值可以是任何可拾取的对象(使用最高协议的 pickle)。
支持在同一数据库文件中存在多个表(即dicts)。
支持从多个线程访问相同的连接(例如Pyro需要)。Vanilla sqlite3给您 ProgrammingError: SQLite objects created in a thread can only be used in that same thread.
并发请求仍在内部序列化,因此这种“多线程支持”不会给您带来任何性能提升。它是Python中sqlite限制的一种解决方案。
支持自定义序列化或压缩
# use JSON instead of pickle
>>> import json
>>> mydict = SqliteDict('./my_db.sqlite', encode=json.dumps, decode=json.loads)
# apply zlib compression after pickling
>>> import zlib, pickle, sqlite3
>>> def my_encode(obj):
... return sqlite3.Binary(zlib.compress(pickle.dumps(obj, pickle.HIGHEST_PROTOCOL)))
>>> def my_decode(obj):
... return pickle.loads(zlib.decompress(bytes(obj)))
>>> mydict = SqliteDict('./my_db.sqlite', encode=my_encode, decode=my_decode)
sqlite高效,可以与大型数据库(多吉字节)有效工作,不受内存限制。
sqlitedict主要是sqlite的一个薄包装器。
items() keys() values() 是逐个迭代的,行在工作线程中加载并排队到内存中。
len() 是调用sqlite来计数行,即扫描整个表。
为了更好的性能,批量写入对象并 commit() 一次。
安装
该模块除了Python本身之外没有其他依赖。最低支持的Python版本是3.7,持续在Python 3.7、3.8、3.9和3.10上测试 在Travis上。
使用以下命令安装或升级
pip install -U sqlitedict
python setup.py install
贡献
测试
安装
$ pip install pytest coverage pytest-coverage
执行所有测试
$ mkdir -p tests/db $ pytest tests $ python -m doctest README.rst
执行所有测试并包含覆盖率
$ pytest tests --cov=sqlitedict
许可证
sqlitedict 是开源软件,在 Apache 2.0许可证 下发布。版权(c)2011-现在 Radim Řehůřek 和贡献者。
管理
清理测试数据库以保持每个doctest运行自包含
>>> import os
>>> if __name__ == '__main__':
... os.unlink('example.sqlite')
项目详情
sqlitedict-2.1.0.tar.gz的散列值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 03d9cfb96d602996f1d4c2db2856f1224b96a9c431bdd16e78032a72940f9e8c |
|
MD5 | 1cd94cbf77b97fadb8dbcdfa5a171d15 |
|
BLAKE2b-256 | 129a7620d1e9dcb02839ed6d4b14064e609cdd7a8ae1e47289aa0456796dd9ca |
评论,错误报告
sqlitedict 位于 github。您可以在那里提交问题或拉取请求。