如何在shelve中使用整数键?

3 投票
2 回答
3515 浏览
提问于 2025-04-16 06:02

我想在shelve里存一个整数作为键。但是当我尝试存储整数键时,它给我报错。

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

我的代码:

#!/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()

我的程序有什么问题,还是说shelve根本不支持整数键?


编辑 1:

在我的程序里,我试图把一个包含ID和名字的字典放到另一个字典里,用ID作为键。然后再把这个字典存到一个文件里。

我需要在使用shelve的同时用Recno或Queue数据库吗?我还是个初学者,这些东西让我感到困惑。

如果我的问题不清楚,请告诉我。

谢谢。

2 个回答

2

在你的例子中,数据库里的键总是整数,所以把它们转换成字符串应该没问题。

这行代码的意思是:data[str(id)] = {"Id": id, "Name": name}

这是我的测试代码:

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)

输出结果是这样的;它的工作方式像字典,所以不会按顺序排列。

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
1

这个shelve模块使用了一个底层的数据库包,比如dbm、gdbm或者bsddb。

所谓的“shelf”,就是一个持久化的、像字典一样的对象。它和“dbm”数据库的不同之处在于,shelf里的值(不是键!)可以是任何Python对象,只要是pickle模块能处理的东西。这包括大多数类的实例、递归数据类型,以及包含很多共享子对象的对象。键是普通的字符串。你可以在示例部分找到相关的证明。

这个应该可以用。下面是我在代码中做的事情 -

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

更新:你可以试试pickle模块。虽然它不是一个键值数据库,但你可以把你的数据结构构建成键值对,然后再发送给pickle -

如果你有一个对象x,还有一个已经打开用于写入的文件对象f,最简单的序列化这个对象的方法只需要一行代码

pickle.dump(x, f)

要再次反序列化这个对象,如果f是一个已经打开用于读取的文件对象:

x = pickle.load(f)

我听说cPicklepickle快很多。如果你有很多数据要存储,可以试试这个。

撰写回答