Problema com o módulo Shelve?
Pergunta
Usar o módulo Shelve me deu um comportamento surpreendente. keys (), iter () e iteritems () não retornam todas as entradas na prateleira! Aqui está o código:
cache = shelve.open('my.cache')
# ...
cache[url] = (datetime.datetime.today(), value)
mais tarde:
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()
E aqui está a saída:
['targets.xml']
['accounts_with_transactions.xml', 'targets.xml']
['targets.xml', 'accounts_with_transactions.xml']
Alguém já encontrou isso antes e há uma solução alternativa sem saber todas as teclas de cache possíveis a priori?
Solução
De acordo com Referência da Biblioteca Python:
... O banco de dados também está (infelizmente) sujeito às limitações do DBM, se for usado - isso significa que (a representação em conserva de) os objetos armazenados no banco de dados devem ser bastante pequenos ...
Isso reproduz corretamente o 'bug':
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()
com a saída:
[]
['trxns.xml', 'foobar.xml']
['foobar.xml', 'trxns.xml']
A resposta, portanto, é não armazenar nada grande - como XML bruto -, mas os resultados dos cálculos em uma prateleira.
Outras dicas
Vendo seus exemplos, meu primeiro pensamento é que cache.has_key()
tem efeitos colaterais, ou seja, essa chamada adicionará teclas ao cache. O que você ganha
print cache.has_key('xxx')
print list(cache.keys())