Problème avec le module d'étagère?
Question
L'utilisation du module d'étagère m'a donné un comportement surprenant. keys (), iter (), et iterItems () ne renvoyez pas toutes les entrées dans l'étagère! Voici le code:
cache = shelve.open('my.cache')
# ...
cache[url] = (datetime.datetime.today(), value)
plus tard:
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()
Et voici la sortie:
['targets.xml']
['accounts_with_transactions.xml', 'targets.xml']
['targets.xml', 'accounts_with_transactions.xml']
Quelqu'un a-t-il rencontré cela auparavant, et y a-t-il une solution de contournement sans connaître toutes les clés de cache possibles a priori?
La solution
Selon le Référence de la bibliothèque Python:
... La base de données est également (malheureusement) soumise aux limites de DBM, si elle est utilisée - cela signifie que (la représentation marinée des) les objets stockés dans la base de données doit être assez petit ...
Cela reproduit correctement le «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()
avec la sortie:
[]
['trxns.xml', 'foobar.xml']
['foobar.xml', 'trxns.xml']
La réponse est donc de ne rien stocker - comme le XML brut - mais plutôt les résultats des calculs dans une étagère.
Autres conseils
En voyant vos exemples, ma première pensée est que cache.has_key()
a des effets secondaires, c'est-à-dire cet appel ajoutera des clés au cache. Qu'obtenez-vous pour
print cache.has_key('xxx')
print list(cache.keys())