Is there a Python persitent data store that has the same functionality as dict (or how to coax "Shelve" to get that)?
I am using Python 3. shelve
is advertised in the documentation as a persistent version of开发者_如何学Go dict
. However, in my usage, it turns out that shelve
does not allow tuples as keys, while dict does:
import shelve
def tryShelve():
db = shelve.open("shelvefile")
db["word1"] = 1
db[("word1", "word2")] = 15
tryShelve()
produces this error:
Traceback (most recent call last):
File "<pyshell#41>", line 1, in <module>
tryShelve()
File "<pyshell#40>", line 4, in tryShelve
db[("word1", "word2")] = 15
File "C:\Python32\lib\shelve.py", line 125, in __setitem__
self.dict[key.encode(self.keyencoding)] = f.getvalue()
AttributeError: 'tuple' object has no attribute 'encode'
The first paragraph in the shelve
module documentation:
A “shelf” is a persistent, dictionary-like object. The difference with “dbm” databases is that the values (not the keys!) in a shelf can be essentially arbitrary Python objects — anything that the pickle module can handle. This includes most class instances, recursive data types, and objects containing lots of shared sub-objects. The keys are ordinary strings.
[emphasis mine]
yaml
module allows tuples as keys:
>>> d = {}
>>> d["word1"] = 1
>>> d[("word1", "word2")] = 15
>>> import yaml
>>> yaml.dump(d)
'word1: 1\n? !!python/tuple [word1, word2]\n: 15\n'
>>> yaml.load(_)
{('word1', 'word2'): 15, 'word1': 1}
Tuples don't work as keys in the Python 2.7.1 version of shelve
either. The 2.7.1 documention suggests looking at the ActiveState Persistent dictionary recipe. Which I tested and it seemed to work using tuples as keys as shown in your example code with the 'csv'
format, although not with the 'jason'
format (and I didn't try 'pickle'
). You'll understand what I mean by 'format' if you look at the recipe.
It appears to me that shelve can't serialize tuples for writing to file.
Consider pickle
as an alternative.
You could use dumps
and loads
to convert your tuples to strings before using them as keys in a shelve. Alternatively, if your tuple only contains literals, you can use repr(your_tuple)
to obtain a string-representation that you can convert back to a tuple using literal_eval
.
To make the conversion more convenient, you could subclass Shelf
and override __getitem__
and __setitem__
to do the conversions automatically on access.
精彩评论