Python shelve erreur OutOfMemory
-
25-09-2019 - |
Question
J'ai des données stockées dans une base de données que je veux traiter. accès DB est très lent, donc j'ai décidé de charger toutes les données dans un dictionnaire avant tout traitement. Cependant, en raison de la taille énorme des données stockées, je reçois une erreur de dépassement de mémoire (je vois plus de 2 concerts utilisés). Je décide donc d'utiliser une structure de données sur le disque, et a découvert que l'utilisation shelve est une option. Voici ce que je fais (pseudo code python)
def loadData():
if (#dict exists on disk):
d = shelve.open(name)
return d
else:
d = shelve.open(name, writeback=True)
#access DB and write data to dict
# d[key] = value
# or for mutable values
# oldValue = d[key]
# newValue = f(oldValue)
# d[key] = newValue
d.close()
d = shelve.open(name, writeback=True)
return d
J'ai deux ou trois questions,
1) Ai-je vraiment besoin de l'écriture différée = True? Que faut-il faire?
2) Je reçois encore une exception mémoire saturée, puisque je n'exerce aucun contrôle sur le moment où les données sont en cours d'écriture sur le disque. Comment je fais ça? J'ai essayé de faire une synchronisation () toutes les quelques itérations, mais cela n'a pas aidé non plus.
Merci!
La solution
writeback=True
oblige l'étagère à garder en mémoire tout élément jamais tiré par les cheveux, et les écrire en arrière quand le plateau est fermé. Ainsi, il consomme beaucoup plus de mémoire et ralentit la fermeture.
L'avantage du paramètre est que, avec elle, vous ne pas besoin du code crispé vous montrez dans vos commentaires pour les articles mutables dont mutator est une méthode - juste
shelf['foobar'].append(23)
œuvres (si shelf
a été ouvert avec writeback activé), en supposant que l'élément à 'foobar'
clé est une liste bien sûr, alors qu'il serait silencieusement une non-opération (en laissant l'élément sur le disque inchangé) si shelf
a été ouvert sans writeback - - dans ce dernier cas, vous avez réellement besoin de code
thelist = shelf['foobar']
thelist.append(23)
shekf['foobar'] = thelist
dans l'esprit de votre commentaire -. Qui est stylistiquement un peu une vraie corvée
Cependant, puisque vous sont ayant des problèmes de mémoire, je vous recommande vraiment pas en utilisant cette option douteuse writeback. Je pense que je peux l'appeler « douteux » depuis que je suis celui qui propose et première mise en œuvre, mais c'était il y a plusieurs années, et je me suis surtout repenti de le faire - il Generales plus de confusion (comme vos preuves Q) que permet élégance et praticité dans le code en mouvement écrit à l'origine pour travailler avec dicts (qui utiliserait le premier idiome, pas le second, et ont donc besoin de réécriture pour être utilisable avec des étagères sans retraçage). Eh bien, désolé, ce ne semble une bonne idée à l'époque.
Autres conseils
Utilisation du module sqlite3
est probablement votre meilleur choix ici. Vous pourriez être en mesure d'utiliser SQLite entièrement en mémoire de toute façon depuis son empreinte mémoire est peut-être un peu plus petit que d'utiliser des objets python de toute façon. Il est généralement un meilleur choix que d'utiliser shelve
de toute façon; shelve
utilise pickle
en dessous, ce qui est rarement ce que vous voulez.
L'enfer, vous pouvez simplement convertir la totalité de votre base de données existante à une base de données SQLite. SQLite est agréable et rapide.