Python中的Shelve模块无法工作:“无法确定数据库类型”

8
我正在尝试用Python制作一个简单的密码存储程序,它看起来很简单,所以我想知道我是否使用shelve有误。
我有主要的.py文件:
import shelve

passwords = shelve.open('./passwords_dict.py')

choice = raw_input("Add password (a) or choose site (c)?")

if choice[0] == 'a':
    site_key = raw_input("Add for which site? ").lower()
    userpass = raw_input("Add any info such as username, email, or passwords: ")

    passwords[site_key] = userpass

else:
    site = raw_input("Which site? ").lower()
    if site in passwords:
        print "Info for " + site + ": " + passwords[site]
    else:
        print site, "doesn't seem to exist!"

print "Done!"

passwords.close()

另一个文件passwords_dict.py只是一个空字典。

但是当我尝试运行程序时,出现了以下错误:

Traceback (most recent call last):
File "passwords.py", line 3, in <module>
passwords = shelve.open('passwords_dict.py')
File "/usr/lib/python2.7/shelve.py", line 239, in open
return DbfilenameShelf(filename, flag, protocol, writeback)
File "/usr/lib/python2.7/shelve.py", line 223, in __init__
Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback)
File "/usr/lib/python2.7/anydbm.py", line 82, in open
raise error, "db type could not be determined"
anydbm.error: db type could not be determined

当我尝试使用anydbm时,出现了以下错误:
Traceback (most recent call last):
File "passwords.py", line 3, in <module>
passwords = anydbm.open('passwords_dict.py')
File "/usr/lib/python2.7/anydbm.py", line 82, in open
raise error, "db type could not be determined"
anydbm.error: db type could not be determined

当我尝试使用dbm时,出现了以下错误:
Traceback (most recent call last):
File "passwords.py", line 3, in <module>
passwords = dbm.open('./passwords_dict.py')
dbm.error: (2, 'No such file or directory')

我做错了什么?还有其他方法可以存储字典并仍能使用用户输入提取键(而不是整个字典,这可能是pickle所做的)吗?
3个回答

7

我认为你对 shelve 模块的工作方式有误解。它打开的是一个数据库文件。当你尝试打开包含 Python 脚本的现有文件时,它会尝试检测该文件包含的数据库类型(因为 shelve 支持多种后端数据库)。

我认为你需要的是以下内容:

import os
import shelve

curdir = os.path.dirname(__file__)
passwords = shelve.open(os.path.join(curdir, 'password_db'))

这将在你的脚本所在的同一目录中创建一个名为password_db.<db>的新文件,其中<db>是特定于实现的数据库文件扩展名。

1
我也遇到了这个问题。它似乎与shelve.openfilename参数的未记录条件有关。目前它是非常不透明的(例如,shelve.open("/tmp/tmphTTQLda")可以正常工作,而shelve.open("/tmp/tmphTTQLd")却不能)。文件名的成功和失败很难预测。我在http://bugs.python.org/issue23174上请求了一个文档增强说明。
在我的情况下,在shelve之外打开持久字典并将其传递给shelve.Shelve可以正常工作,例如代码:
a = dumbdbm.open(tempfile.mkstemp()[1])
b = shelve.Shelf(dict=a)

并且对于shelve.open的返回值,您需要像处理b一样进行操作。

抱歉,什么是tempfile?如果tempfile已经存在,这也能起作用吗? - Arnold Roa
tempfile 是一个标准的 Python 模块。根据定义,tempfile.mkstemp 应该创建一个不存在的文件。 - Kalle Richter

0

为什么不直接import gdbm,然后稍后使用file = shelve.Shelf(gdbm.open(filename, flag)),这似乎更符合Python的风格呢? - cnaak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接