Модуль полки в python не работает: невозможно определить тип базы данных

Я пытаюсь создать простую программу для хранения паролей на Python, и она кажется довольно простой, поэтому мне интересно, неправильно ли я использую полку.

У меня есть основной файл .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')

Что я делаю не так? Есть ли другой способ сохранить словарь и по-прежнему иметь возможность извлекать ключи, используя пользовательский ввод (а не весь словарь, что, я полагаю, и делает рассол)?


person yung galbanum    schedule 23.05.2013    source источник


Ответы (3)


Я думаю, вы неправильно понимаете, как работает модуль полки. Он открывает файл базы данных. Когда вы пытаетесь открыть существующий файл, содержащий сценарий Python, он пытается определить, какой тип базы данных содержит файл (поскольку shelve поддерживает несколько серверных баз данных).

Я думаю, вместо этого вы хотите что-то вроде этого:

import os
import shelve

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

Это создаст новый файл в том же каталоге, что и ваш сценарий, с именем password_db.<db>, где <db> — это расширение файла базы данных, зависящее от реализации.

person jterrace    schedule 23.05.2013

Я тоже столкнулся с этой проблемой. Кажется, это связано с недокументированными условиями для аргумента filename аргумента shelve.open. В настоящее время он очень непрозрачен (например, 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)

и сделайте с b то, что вы сделали бы с возвращаемым значением shelve.open.

person Karl Richter    schedule 07.02.2015
comment
извините, какой у него временный файл? это также работает, если временный файл уже существует? - person Arnold Roa; 03.03.2016
comment
tempfile — это стандартный модуль Python. tempfile.mkstemp должен создать несуществующий файл по определению. - person Karl Richter; 03.03.2016

Существует одна ошибка с любой базой данных https://bugs.python.org/issue13007, которая не могла использовать правильная идентификация для gdbm файлов.

Поэтому, если вы пытаетесь открыть действительный файл gdbm с полкой и испытываете эту ошибку, используйте это вместо этого:

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

Дополнительная информация по этому вопросу: полка db тип не может быть определен, какая база данных не распознает gdb

person Arnold Roa    schedule 03.03.2016
comment
Почему бы не просто import gdbm, а затем file = shelve.Shelf(gdbm.open(filename, flag)), что кажется более питоническим? - person cnaak; 18.09.2016