una txt tag parser open lista linea leer importar especifica escribir ejercicios como archivos archivo python performance memory mmap

txt - open en python



¿Por qué el mmap de Python no funciona con archivos grandes? (8)

Use una computadora de 64 bits, con un sistema operativo de 64 bits y una implementación de Python de 64 bits, o evite memmap()

memmap() requiere soporte de hardware de CPU para que tenga sentido con archivos de gran tamaño mayores que unos pocos GiB.

Utiliza la MMU la CPU e interrumpe los subsistemas para permitir la exposición de los datos como si ya estuviera cargada RAM.

La MMU es hardware que generará una interrupción cuando se accede a una dirección correspondiente a datos que no están en la RAM física, y el SO manejará la interrupción de manera que tenga sentido en tiempo de ejecución, por lo que el código de acceso nunca lo sabe (o necesita saber) que los datos no encajan en la RAM.

Esto hace que su código de acceso sea simple de escribir. Sin embargo, para usar memmap() esta manera, todo lo que esté involucrado necesitará manejar direcciones de 64 bits.

O bien, puede ser preferible evitar memmap() completo y hacer su propia gestión de memoria.

[Editar: Este problema se aplica solo a sistemas de 32 bits. Si su computadora, su sistema operativo y su implementación Python son de 64 bits, entonces el mmap-ing de archivos de gran tamaño funciona de manera confiable y es extremadamente eficiente.]

Estoy escribiendo un módulo que, entre otras cosas, permite el acceso de lectura bit a bit a los archivos. Los archivos pueden ser potencialmente grandes (cientos de GB), así que escribí una clase simple que me permite tratar el archivo como una cadena y esconder todo lo que busca y lee.

En el momento en que escribí mi clase contenedora no sabía sobre el módulo mmap . Al leer la documentación de mmap, pensé "genial - esto es justo lo que necesitaba, sacaré mi código y lo reemplazaré con un mmap. Probablemente sea mucho más eficiente y siempre es bueno borrar el código".

¡El problema es que mmap no funciona para archivos grandes! Esto es muy sorprendente para mí, ya que pensé que era quizás la aplicación más obvia. Si el archivo está por encima de algunos gigabytes entonces obtengo un EnvironmentError: [Errno 12] Cannot allocate memory . Esto solo ocurre con una versión de Python de 32 bits, por lo que parece que se está quedando sin espacio de direcciones, pero no puedo encontrar ninguna documentación al respecto.

Mi código es solo

f = open(''somelargefile'', ''rb'') map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)

Entonces mi pregunta es ¿me estoy perdiendo algo obvio aquí? ¿Hay alguna manera de hacer que mmap funcione de forma portátil en archivos grandes o debería volver a mi contenedor de archivos ingenuo?

Actualización: parece haber una sensación de que el mmap de Python debería tener las mismas restricciones que el mmap de POSIX. Para expresar mejor mi frustración aquí, hay una clase simple que tiene una pequeña parte de la funcionalidad de mmap.

import os class Mmap(object): def __init__(self, f): """Initialise with a file object.""" self.source = f def __getitem__(self, key): try: # A slice self.source.seek(key.start, os.SEEK_SET) return self.source.read(key.stop - key.start) except AttributeError: # single element self.source.seek(key, os.SEEK_SET) return self.source.read(1)

Es de solo lectura y no sirve para nada, pero puedo hacer lo mismo que con un mmap:

map2 = Mmap(f) print map2[0:10] print map2[10000000000:10000000010]

excepto que no hay restricciones en el tamaño del archivo. No es muy difícil realmente ...


De IEEE 1003.1:

La función mmap () establecerá una asignación entre el espacio de direcciones de un proceso y un archivo, objeto de memoria compartida o objeto de memoria tipeado [TYM].

Necesita todo el espacio de direcciones virtual porque eso es exactamente lo que hace mmap() .

El hecho de que realmente no se está quedando sin memoria no importa; no puede mapear más espacio de direcciones del que tiene disponible. Como entonces toma el resultado y accede como si fuera memoria, ¿cómo se propone acceder exactamente a más de 2 ^ 32 bytes en el archivo? Incluso si mmap() no fallara, aún podría leer los primeros 4GB antes de quedarse sin espacio en un espacio de direcciones de 32 bits. Puede, por supuesto, mmap() una ventana deslizante de 32 bits sobre el archivo, pero eso no necesariamente redituará ningún beneficio a menos que pueda optimizar su patrón de acceso de modo que limite cuántas veces tiene que visitar ventanas anteriores.


El módulo mmap proporciona todas las herramientas que necesita para hurgar en su archivo grande, pero debido a las limitaciones que otras personas han mencionado, no puede asignarlo todo a la vez . Puedes mapear un pedazo de buen tamaño de una vez, hacer un poco de procesamiento y luego desasignarlo y asignar otro. los argumentos clave para la clase mmap son length y offset , que hacen exactamente lo que parecen, lo que le permite mapear bytes de length , comenzando en el offset bytes en el archivo asignado. Cada vez que desee leer una sección de la memoria que está fuera de la ventana mapeada, debe mapear en una nueva ventana.


El punto que te falta es que mmap es una función de mapeo de memoria que asigna un archivo a la memoria para el acceso arbitrario a través del rango de datos solicitado por cualquier medio.

Lo que está buscando suena más como una clase de ventana de datos que presenta una API que le permite ver pequeñas ventanas de una gran estructura de datos en cualquier momento. El acceso más allá de los límites de esta ventana no sería posible más que llamando a la propia API de la ventana de datos.

Esto está bien, pero no es un mapa de memoria, es algo que ofrece la ventaja de un rango de datos más amplio a costa de una API más restrictiva.


Está configurando el parámetro de longitud a cero, lo que significa que se debe asignar en todo el archivo. En una compilación de 32 bits, esto no será posible si la longitud del archivo es más de 2 GB (posiblemente 4 GB).


Le pide al sistema operativo que asigne el archivo completo en un rango de memoria. No se leerá hasta que desencadene fallas de página leyendo / escribiendo, pero aún necesita asegurarse de que todo el rango esté disponible para su proceso, y si ese rango es demasiado grande, habrá dificultades.


Perdón por responder mi propia pregunta, pero creo que el verdadero problema que tenía no era saber que mmap era una llamada al sistema POSIX estándar con caracterizaciones y limitaciones particulares, y que Python mmap se supone que solo expone su funcionalidad.

La documentación de Python no menciona el mmap de POSIX y, por lo tanto, si usted lo considera un programador de Python sin mucho conocimiento de POSIX (como yo lo hice), entonces el problema del espacio de direcciones parece bastante arbitrario y mal diseñado.

Gracias a los otros carteles por enseñarme el verdadero significado de mmap. Desafortunadamente, nadie ha sugerido una mejor alternativa a mi clase hecha a mano para tratar grandes archivos como cadenas, así que tendré que seguir con esto por ahora. Tal vez lo limpie y lo haga parte de la interfaz pública de mi módulo cuando tenga la oportunidad.


Un programa y un sistema operativo de 32 bits solo pueden abordar un máximo de 32 bits de memoria, es decir, 4 GB. Hay otros factores que hacen que el total sea aún más pequeño; por ejemplo, Windows se reserva entre 0.5 y 2GB para el acceso de hardware, y por supuesto su programa también va a tomar algo de espacio.

Editar: Lo obvio que te hace falta es una comprensión de la mecánica de mmap, en cualquier sistema operativo. Le permite asignar una parte de un archivo a un rango de memoria: una vez que lo haya hecho, cualquier acceso a esa parte del archivo ocurre con la menor sobrecarga posible. Su sobrecarga es baja porque la asignación se realiza una vez y no tiene que cambiar cada vez que accede a un rango diferente. El inconveniente es que necesita un rango de direcciones abierto suficiente para la parte que está tratando de asignar. Si está mapeando todo el archivo a la vez, necesitará un agujero en el mapa de memoria lo suficientemente grande como para caber todo el archivo. Si tal agujero no existe, o es más grande que su espacio de direcciones completo, falla.