Проблема с полочным модулем?

Использование модуля полки дало мне некоторое неожиданное поведение. keys(), iter() и iteritems() не возвращают все записи на полке! Вот код:

cache = shelve.open('my.cache')
# ...
cache[url] = (datetime.datetime.today(), value)

потом:

cache = shelve.open('my.cache')
urls = ['accounts_with_transactions.xml', 'targets.xml', 'profile.xml']
try:
    print list(cache.keys()) # doesn't return all the keys!
    print [url for url in urls if cache.has_key(url)]
    print list(cache.keys())
finally:
    cache.close()

и вот результат:

['targets.xml']
['accounts_with_transactions.xml', 'targets.xml']
['targets.xml', 'accounts_with_transactions.xml']

Кто-нибудь сталкивался с этим раньше, и есть ли обходной путь, не зная всех возможных ключей кэша априори?


person Michael Deardeuff    schedule 25.08.2009    source источник
comment
Какой модуль dbm вы используете? Звучит как ошибка для меня.   -  person Martin v. Löwis    schedule 25.08.2009
comment
whichdb.whatdb('my.cache') =› дбм   -  person Michael Deardeuff    schedule 25.08.2009
comment
(кстати, это Python 2.5 на Mac)   -  person Michael Deardeuff    schedule 25.08.2009
comment
Можете ли вы показать код вашего метода put? Это не часть стандартного класса полки.   -  person Ned Deily    schedule 25.08.2009


Ответы (2)


Согласно справочнику по библиотеке Python:

... База данных также (к сожалению) подвержена ограничениям dbm, если она используется - это означает, что (маринованное представление) объекты, хранящиеся в базе данных, должны быть довольно маленькими...

Это правильно воспроизводит «ошибку»:

import shelve

a = 'trxns.xml'
b = 'foobar.xml'
c = 'profile.xml'

urls = [a, b, c]
cache = shelve.open('my.cache', 'c')

try:
    cache[a] = a*1000
    cache[b] = b*10000
finally:
    cache.close()


cache = shelve.open('my.cache', 'c')

try:
    print cache.keys()
    print [url for url in urls if cache.has_key(url)]
    print cache.keys()
finally:
    cache.close()

с выводом:

[]
['trxns.xml', 'foobar.xml']
['foobar.xml', 'trxns.xml']

Следовательно, ответ таков: не храните ничего большого, например необработанный xml, а лучше храните результаты вычислений на полке.

person Michael Deardeuff    schedule 25.08.2009
comment
В Python 2.6 я не могу воспроизвести эту ошибку. - person Nicolas Dumazet; 25.08.2009
comment
Возможно, вы не используете dbm, попробуйте whichdb.whatdb('my.cache'). На моем Mac он производит «dbm». Я еще не пробовал это на других системах. - person Michael Deardeuff; 25.08.2009

Увидев ваши примеры, моя первая мысль, что cache.has_key() имеет побочные эффекты, т.е. этот вызов добавит ключи в кеш. Что вы получаете за

print cache.has_key('xxx')
print list(cache.keys())
person Aaron Digulla    schedule 25.08.2009
comment
Я обновил код вопроса, указав сокращенную версию URL-адресов. - person Michael Deardeuff; 25.08.2009
comment
Все еще не вычисляет; вы добавляете один URL-адрес в кеш, но после has_key в кеше есть два URL-адреса. Должен быть какой-то побочный эффект. - person Aaron Digulla; 25.08.2009
comment
В кеше на самом деле есть 2 URL-адреса. но keys() не показывает их обоих, пока я не проверю их явно. - person Michael Deardeuff; 25.08.2009
comment
Можете ли вы опубликовать has_key(), пожалуйста? - person Aaron Digulla; 25.08.2009