问题
I want to store an integer key in shelve. But when I try to store integer key in shelve it give me an error
Traceback (most recent call last): File "./write.py", line 12, in data[id] = {"Id": id, "Name": name} File "/usr/lib/python2.5/shelve.py", line 124, in __setitem__ self.dict[key] = f.getvalue() File "/usr/lib/python2.5/bsddb/__init__.py", line 230, in __setitem__ _DeadlockWrap(wrapF) # self.db[key] = value File "/usr/lib/python2.5/bsddb/dbutils.py", line 62, in DeadlockWrap return function(*_args, **_kwargs) File "/usr/lib/python2.5/bsddb/__init__.py", line 229, in wrapF self.db[key] = value TypeError: Integer keys only allowed for Recno and Queue DB's
My Code :
#!/usr/bin/python
import shelve
data = shelve.open("data.txt")
ans = 'y'
while ans == "y":
id = input("Enter Id : ")
name = raw_input("Enter name : ")
data[id] = {"Id": id, "Name": name}
ans = raw_input("Do you want to continue (y/n) ? : ")
data.close()
Is something wrong in my program or shelve does not supports integer keys at all ?
Edit 1 :
In program I am trying to store a dictionary of Id and Name inside another dictionary with Id as a key. And then trying to store it in a file.
Do I need to use Recno or Queue DB's along with shelve? I am a beginner and things are confusing.
Let me know if I am not clear with my question.
Thanks.
回答1:
The shelve module uses an underlying database package (such as dbm, gdbm or bsddb) .
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. The examples section gives you the proof.
This should work. Here's what I do in my code -
import shelve
#Create shelve
s = shelve.open('test_shelf.db')
try:
s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
finally:
s.close()
#Access shelve
s = shelve.open('test_shelf.db')
try:
existing = s['key1']
finally:
s.close()
print existing
UPDATE: You could try pickle
module. It is not a key-value database but you can always build your data structure as a key-value pairs and then send it to pickle
-
If you have an object x, and a file object f that's been opened for writing, the simplest way to pickle the object takes only one line of code
pickle.dump(x, f)
To unpickle the object again, if f is a file object which has been opened for reading:
x = pickle.load(f)
I hear cPickle
is a lot faster than pickle
. You can try this if you have lot of data to store.
回答2:
In your example the keys in your database will always be integers, so it should work fine to convert them to strings,
data[str(id)] = {"Id": id, "Name": name}
My test code
def shelve_some_data(filename):
db = shelve.open(filename, flag="c")
try:
# note key has to be a string
db[str(1)] = "1 integer key that's been stringified"
db[str(2)] = "2 integer key that's been stringified"
db[str(3)] = "3 integer key that's been stringified"
db[str(10)] = "10 integer key that's been stringified"
finally:
db.close()
def whats_in(filename):
db = shelve.open(filename, flag="r")
for k in db:
print("%s : %s" % (k, db[k]))
return
filename = "spam.db"
shelve_some_data(filename)
whats_in(filename)
And the output; it works like a dict so it's not sorted.
2 : 2 integer key that's been stringified
10 : 10 integer key that's been stringified
1 : 1 integer key that's been stringified
3 : 3 integer key that's been stringified
来源:https://stackoverflow.com/questions/4013452/how-do-i-take-integer-keys-in-shelve