Package: litedict
litedictDictionary implemented on top of SQLiteWhy?You can use this to implement a persistent dictionary. It also uses some SQLite syntax to enable getting keys using pattern matching (see examples).Installationpip install litedictAlternativesRaRe-Technologies/sqlitedict: This library uses a separate writing thread. Modern versions of SQLite are thread safe by default (serialized), so a separate writing thread is not strictly needed. It can be helpful to avoid DB locks, but it also adds extra complexity. That implementation is also missing some performance optimizations that are present in this repository.ExamplesThe examples are taken from the tests intests.ipynbfromlitedictimportSQLDictTEST_1="key_test_1"TEST_2="key_test_2"Basic functionalityd=SQLDict(":memory:")d[TEST_1]="asdfoobar"assertd[TEST_1]=="asdfoobar"deld[TEST_1]assertd.get(TEST_1,None)isNone# execute multiple instructions inside a transactionwithd.transaction():d["asd"]="efg"d["foo"]="bar"Glob matchingd[TEST_1]="asdfoobar"d[TEST_2]="foobarasd"d["key_testx_3"]="barasdfoo"assertd.glob("key_test*")==["asdfoobar","foobarasd","barasdfoo"]assertd.glob("key_test_?")==["asdfoobar","foobarasd"]assertd.glob("key_tes[tx]*")==["asdfoobar","foobarasd","barasdfoo"]Numbersd[TEST_1]=1d[TEST_2]=2assertd[TEST_1]+d[TEST_2]==3Benchmarksfromstringimportascii_lowercase,printablefromrandomimportchoiceimportrandomdefrandom_string(string_length=10,fuzz=False,space=False):"""Generate a random string of fixed length """letters=ascii_lowercaseletters=letters+" "ifspaceelselettersiffuzz:letters=printablereturn"".join(choice(letters)foriinrange(string_length))importgcimportpickleimportjsonPickled=SQLDict(":memory:",encoder=lambdax:pickle.dumps(x).hex(),decoder=lambdax:pickle.loads(bytes.fromhex(x)),)gc.collect()# %%timeit -n20000 -r10d[random_string(8)]=random_string(50)d.get(random_string(8),None)# 69.2 µs ± 4.84 µs per loop (mean ± std. dev. of 10 runs, 20000 loops each)Noopd=SQLDict(":memory:",encoder=lambdax:x,decoder=lambdax:x,)gc.collect()# %%timeit -n20000 -r10d[random_string(8)]=random_string(50)d.get(random_string(8),None)# 66.8 µs ± 2.41 µs per loop (mean ± std. dev. of 10 runs, 20000 loops each)JSONd=SQLDict(":memory:",encoder=lambdax:json.dumps(x),decoder=lambdax:json.loads(x),)gc.collect()# %%timeit -n20000 -r10d[random_string(8)]=random_string(50)d.get(random_string(8),None)# 68.6 µs ± 3.07 µs per loop (mean ± std. dev. of 10 runs, 20000 loops each)Pickle Python objd=SQLDict(":memory:",encoder=lambdax:pickle.dumps(x).hex(),decoder=lambdax:pickle.loads(bytes.fromhex(x)),)gc.collect()classC:def__init__(self,x):self.x=xdefpp(self):returnxdeff(self):def_f(y):returny*self.x**2return_f# %%timeit -n20000 -r10d[random_string(8)]=C(random.randint(1,200))d.get(random_string(8),None)# 41.1 µs ± 2.75 µs per loop (mean ± std. dev. of 10 runs, 20000 loops each)Dictionaryd={}gc.collect()# %%timeit -n20000 -r10d[random_string(8)]=random_string(50)d.get(random_string(8),None)# 53.1 µs ± 4.42 µs per loop (mean ± std. dev. of 10 runs, 20000 loops each)Changelog0.3Add transactions as part of the dictionaryMetaRicardo Ander-Egg Aguilar –@ricardoanderegg–ricardoanderegg.comgithub.com/polyrandlinkedin.com/in/ricardoandereggDistributed under the MIT license. SeeLICENSEfor more information.ContributingThe only hard rules for the project are:No extra dependencies allowedNo extra files, everything must be inside the main module's.pyfile.Tests must be inside thetests.ipynbnotebook.