objeto - Alternativas para mantener listas grandes en la memoria(python)
limpiar variables en python (9)
¿Revisaste el módulo shelve python que se basa en pickle?
Si tengo una lista (o matriz, diccionario ....) en python que podría exceder el espacio de direcciones de memoria disponible, (32 bit python) ¿cuáles son las opciones y las velocidades relativas? (aparte de no hacer una lista tan grande) La lista podría exceder la memoria pero no tengo forma de saberlo de antemano. Una vez que comience a exceder el 75%, me gustaría dejar de mantener la lista en la memoria (o los nuevos elementos de todos modos), ¿hay alguna manera de convertir a un enfoque basado en archivos a mitad de camino?
¿Cuáles son las mejores opciones de almacenamiento de archivos (velocidad de entrada y salida)?
Solo necesita almacenar una simple lista de números. no es necesario un acceso aleatorio al elemento Nth, solo operaciones de tipo append / pop.
Es posible que desee considerar un tipo diferente de estructura: no una lista, sino averiguar cómo hacerlo (su tarea) con un generador o un iterador personalizado.
La respuesta es mucho "depende".
¿Qué estás almacenando en las listas? ¿Instrumentos de cuerda? enteros? ¿Objetos?
¿Con qué frecuencia se escribe la lista en comparación con la lectura? ¿Los artículos solo se añaden al final o las entradas se pueden modificar o insertar en el medio?
Si solo está agregando hasta el final, escribir en un archivo plano puede ser lo más simple que pueda funcionar.
Si está almacenando objetos de tamaño variable como cadenas, puede mantener un índice en la memoria del inicio de cada cadena, para que pueda leerlo rápidamente.
Si desea un comportamiento del diccionario, mire los módulos db - dbm, gdbm, bsddb, etc.
Si desea escribir con acceso aleatorio, tal vez una base de datos SQL sea mejor.
Hagas lo que hagas, ir al disco va a ser órdenes de magnitud más lentas que en la memoria, pero sin saber cómo se usarán los datos, es imposible ser más específico.
editar: a partir de sus requisitos actualizados, iría con un archivo plano y mantendría un buffer en memoria de los últimos N elementos.
Los sistemas operativos modernos se encargarán de esto sin tener que preocuparse por ello. Se llama memoria virtual .
Probablemente haya docenas de formas de almacenar los datos de su lista en un archivo en lugar de en la memoria. La forma de elegir dependerá completamente del tipo de operaciones que necesite realizar sobre los datos. ¿Necesitas acceso aleatorio al N-ésimo elemento? ¿Necesitas iterar sobre todos los elementos? ¿Estará buscando elementos que coincidan con ciertos criterios? ¿Qué forma toman los elementos de la lista? ¿Solo estará insertando al final de la lista, o también en el medio? ¿Hay metadatos que pueda mantener en la memoria con la mayor parte de los elementos en el disco? Y así sucesivamente y así sucesivamente.
Una posibilidad es estructurar sus datos relacionalmente y almacenarlos en una base de datos SQLite.
Si sus "números" son suficientemente simples (enteros con signo o sin signo de hasta 4 bytes cada uno, o flotantes de 4 u 8 bytes cada uno), recomiendo el módulo de conjunto de bibliotecas estándar como la mejor manera de mantener algunos millones de ellos en la memoria (la "punta" de su "matriz virtual") con un archivo binario (abierto para R / W binario) que respalda el resto de la estructura en el disco. array.array
tiene métodos de fromfile
y tofile
array.array
muy rápidos para facilitar el movimiento de datos hacia adelante y hacia atrás.
Es decir, básicamente, suponiendo, por ejemplo, números sin signo, algo así como:
import os
# no more than 100 million items in memory at a time
MAXINMEM = int(1e8)
class bigarray(object):
def __init__(self):
self.f = open(''afile.dat'', ''w+'')
self.a = array.array(''L'')
def append(self, n):
self.a.append(n)
if len(self.a) > MAXINMEM:
self.a.tofile(self.f)
del self.a[:]
def pop(self):
if not len(self.a):
try: self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
except IOError: return self.a.pop() # ensure normal IndexError &c
try: self.a.fromfile(self.f, MAXINMEM)
except EOFError: pass
self.f.seek(-self.a.itemsize * MAXINMEM, os.SEEK_END)
self.f.truncate()
return self.a.pop()
Por supuesto, puede agregar otros métodos según sea necesario (por ejemplo, realizar un seguimiento de la longitud total, agregar extend
, lo que sea), pero si pop
y append
son de hecho todo lo que necesita, esto debería servir.
Puedes probar blist: https://pypi.python.org/pypi/blist/
El blist es un reemplazo directo para la lista de Python que proporciona un mejor rendimiento cuando se modifican listas grandes.
¿Qué tal una base de datos orientada a documentos?
Hay varias alternativas; Creo que el más conocido actualmente es CouchDB , pero también puedes elegir Tokyo Cabinet o MongoDB . El último tiene la ventaja de enlaces de python directamente desde el proyecto principal, sin requerir ningún módulo adicional.