跳转到主要内容

Python中的持久化字典,由sqlite3和pickle支持,线程安全。

项目描述

GithubActions License

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

或从 source tar.gz

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 位于 github。您可以在那里提交问题或拉取请求。

许可证

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 (21.8 kB 查看散列值)

上传时间 源代码

支持者