Puede que esté utilizando una herramienta incorrecta para este trabajo. Si desea conservar una gran cantidad de datos indexados, le sugiero que use una base de datos SQLite en disco (o, por supuesto, solo una base de datos normal) con un ORM como SQLObject o SQL Alchemy.
Estos se hará cargo de las cosas mundanas como la compatibilidad, la optimización de formato para el propósito, y no posee la totalidad de los datos en la memoria al mismo tiempo para que se agote la memoria ...
Agregado: Porque estaba trabajando en algo casi idéntico de todos modos, pero principalmente porque soy una persona agradable, aquí hay una demostración que parece hacer lo que necesita (creará un archivo SQLite en su directorio actual, y lo eliminará si un archivo con ese el nombre ya existe, así que colóquelo en algún lugar vacío primero):
import sqlobject
from sqlobject import SQLObject, UnicodeCol, ForeignKey, IntCol, SQLMultipleJoin
import os
DB_NAME = "mydb"
ENCODING = "utf8"
class Document(SQLObject):
dbName = UnicodeCol(dbEncoding=ENCODING)
class Location(SQLObject):
""" Location of each individual occurrence of a word within a document.
"""
dbWord = UnicodeCol(dbEncoding=ENCODING)
dbDocument = ForeignKey('Document')
dbLocation = IntCol()
TEST_DATA = {
'one' : {
'doc1' : [1,2,10],
'doc3' : [6],
},
'two' : {
'doc1' : [2, 13],
'doc2' : [5,6,7],
},
'three' : {
'doc3' : [1],
},
}
if __name__ == "__main__":
db_filename = os.path.abspath(DB_NAME)
if os.path.exists(db_filename):
os.unlink(db_filename)
connection = sqlobject.connectionForURI("sqlite:%s" % (db_filename))
sqlobject.sqlhub.processConnection = connection
# Create the tables
Document.createTable()
Location.createTable()
# Import the dict data:
for word, locs in TEST_DATA.items():
for doc, indices in locs.items():
sql_doc = Document(dbName=doc)
for index in indices:
Location(dbWord=word, dbDocument=sql_doc, dbLocation=index)
# Let's check out the data... where can we find 'two'?
locs_for_two = Location.selectBy(dbWord = 'two')
# Or...
# locs_for_two = Location.select(Location.q.dbWord == 'two')
print "Word 'two' found at..."
for loc in locs_for_two:
print "Found: %s, p%s" % (loc.dbDocument.dbName, loc.dbLocation)
# What documents have 'one' in them?
docs_with_one = Location.selectBy(dbWord = 'one').throughTo.dbDocument
print
print "Word 'one' found in documents..."
for doc in docs_with_one:
print "Found: %s" % doc.dbName
Esto es cert Ainly no es la única forma (o necesariamente la mejor) para hacer esto. Si las tablas de documento o de Word deben ser tablas separadas de la tabla de ubicación depende de sus datos y uso típico. En su caso, la tabla "Word" probablemente sea una tabla separada con algunas configuraciones adicionales para indexación y unicidad.
Funcionó como un amuleto. Solución increíblemente simple: básicamente cambió "pickle" a "mariscal" y ya estaba hecho. No me di cuenta de que cPickle realizaba la detección de ciclo. Al usar Mariscal en su lugar, escribir en el disco tomó una cuestión de segundos en lugar de 20 minutos, y redujo el consumo de memoria del 30% y se estrelló a casi 0%. ¡Gracias! –
Solución simple más una explicación concisa, 100% impresionante. – mitchus
¡Es bueno saberlo, gracias @gnibbler! –