2013-05-23 19 views
6

Sto cercando di creare un semplice programma di memorizzazione delle password in Python, e sembra piuttosto semplice, quindi mi chiedo se sto usando shelve errato.Il modulo Shelve in python non funziona: "il tipo db non può essere determinato"

ho il principale file di .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() 

E l'altro file, passwords_dict.py, è solo un dizionario vuoto.

Ma quando provo a fare funzionare il programma, ottengo questo errore:

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 

Quando provo ad usare anydbm invece, ottengo questo errore:

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 

E quando cerco di uso invece dbm, ottengo questo errore:

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

Cosa sto facendo male? C'è un altro modo per memorizzare un dizionario ed essere ancora in grado di estrarre le chiavi usando l'input dell'utente (piuttosto che l'intero dizionario, che suppongo sia ciò che fa pickle)?

risposta

5

Penso che tu abbia frainteso il funzionamento del modulo shelve. Apre un file di database. Quando si tenta di aprire un file esistente che contiene uno script Python, si sta tentando di rilevare il tipo di database che il file contiene (poiché shelve supporta più database di back-end).

Penso invece volete qualcosa di simile:

import os 
import shelve 

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

Questo creerà un nuovo file nella stessa directory script chiamato password_db.<db> dove <db> è un'estensione file di database specifico dell'implementazione.

0

Ho riscontrato questo problema. Sembra essere correlato alle condizioni non documentate per l'argomento filename di shelve.open. Attualmente è molto poco trasparente (ad esempio, shelve.open("/tmp/tmphTTQLda") funziona mentre non lo è lo shelve.open("/tmp/tmphTTQLd")). Il fallimento e il successo dei nomi di file variabili sono difficili da prevedere. Ho richiesto una spiegazione in forma di miglioramento della documentazione allo http://bugs.python.org/issue23174.

Nel mio caso aprire un dict persistente fuori shelve e passarlo a shelve.Shelve opere, ad es. Codice

a = dumbdbm.open(tempfile.mkstemp()[1]) 
b = shelve.Shelf(dict=a) 

e fare con b quello che ci avete fatto con il valore di ritorno di shelve.open.

+0

dispiace, che cosa è la sua tempfile? questo funziona anche se il tempfile esiste già? –

+0

'tempfile' è un modulo python standard. 'Tempfile.mkstemp' dovrebbe creare un file inesistente per definizione. –

0

C'è un bug con anydb https://bugs.python.org/issue13007 che non può utilizzare l'identificazione corretta per i file gdbm.

Quindi, se si sta tentando di aprire un file gdbm valida con ripiano e viene thorwing che l'uso di errore questo, invece:

mod = __import__("gdbm") 
    file = shelve.Shelf(mod.open(filename, flag)) 

Maggiori informazioni su questa questione: shelve db type could not be determined, whichdb is not recognizing gdb

+0

Perché non solo "import gdbm', quindi in seguito' file = shelve.Shelf (gdbm.open (filename, flag)) ', che sembra essere molto più pythonic? – cnaak