Shelve module in python not working: "db type cannot be determined"
Asked Answered
A

3

8

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)?

Arbe answered 23/5, 2013 at 2:56 Comment(0)
G
7

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.

Greatgranduncle answered 23/5, 2013 at 3:7 Comment(0)
I
1

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.

Ishmael answered 7/2, 2015 at 13:12 Comment(2)
sorry, whats its tempfile? this works also if the tempfile already exists?Pocosin
tempfile is a standard python module. tempfile.mkstemp should create an inexisting file by definition.Ishmael
P
0

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

Pocosin answered 3/3, 2016 at 20:15 Comment(1)
Why not just import gdbm, then later file = shelve.Shelf(gdbm.open(filename, flag)), which seems to be way more pythonic?Washcloth

© 2022 - 2024 — McMap. All rights reserved.