I am trying to make a simple password-storing program in Python, and it seems pretty simple so I am wondering if I am using shelve wrong.
I have the main .py file:
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()
And the other file, passwords_dict.py, is just an empty dictionary.
But when I try to run the program, I get this error:
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
When I try to use anydbm instead, I get this error:
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
And when I try to use dbm instead, I get this error:
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')
What am I doing wrong? Is there another way to store a dictionary and still be able to extract keys using user input (rather than the entire dictionary, which I suppose is what pickle does)?
I think you're misunderstanding how the shelve module works. It opens a database file. When you try and open an existing file that contains a Python script, it's trying to detect what database type the file contains (since shelve supports multiple backend databases).
I think instead you want something like this:
import os
import shelve
curdir = os.path.dirname(__file__)
passwords = shelve.open(os.path.join(curdir, 'password_db'))
This will create a new file in the same directory as your script called password_db.<db>
where <db>
is an implementation-specific database file extension.
I've experienced this issue as well. It seems to be related to undocumented conditions for the filename
argument of shelve.open
. It is currently very intransparent (e.g. shelve.open("/tmp/tmphTTQLda")
works while shelve.open("/tmp/tmphTTQLd")
doesn't). Failure and success of variable filenames are hard to predict. I requested an explanation in form a documentation enhancement at http://bugs.python.org/issue23174.
In my case opening a persistent dict outside shelve
and passing it to shelve.Shelve
works, e.g. code
a = dumbdbm.open(tempfile.mkstemp()[1])
b = shelve.Shelf(dict=a)
and do with b
what you'd have done with the return value of shelve.open
.
There is one bug with anydb https://bugs.python.org/issue13007 that could not use the right identification for gdbm
files.
So if you are trying to open a valid gdbm file with shelve and is thorwing that error use this instead:
mod = __import__("gdbm")
file = shelve.Shelf(mod.open(filename, flag))
More information on this question: shelve db type could not be determined, whichdb is not recognizing gdb
来源:https://stackoverflow.com/questions/16704932/shelve-module-in-python-not-working-db-type-cannot-be-determined