开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜