mmap en Python: archivos en memoria

Publicado el: 09/08/2026
Tempo de leitura: 6 minutos
Disco duro que representa archivos mapeados en memoria con mmap en Python

Los archivos grandes pueden procesarse sin cargar todo su contenido manualmente en un único objeto de bytes. mmap en Python crea un mapeo entre una región del archivo y el espacio de memoria virtual del proceso. El objeto resultante se comporta al mismo tiempo como archivo y como array mutable de bytes.

La técnica sirve para búsquedas de patrones, índices binarios, almacenamiento embebido, comunicación entre procesos y actualización de regiones fijas. No hace que cualquier operación sea automáticamente más rápida y exige atención a permisos, alineación, concurrencia, tamaño y persistencia. Esta guía cubre lectura, escritura, copy-on-write, memoria anónima, diferencias entre plataformas, flushing y cierre de recursos.

El contenido complementa nuestras guías sobre fileinput, linecache, tempfile, filecmp y weakref.

Cómo funciona el mapeo

El sistema operativo asocia páginas del archivo con direcciones virtuales. Las páginas se cargan bajo demanda y el kernel gestiona caché y expulsión. Python puede usar índices, slices, búsquedas y métodos similares a archivos.

El coste del almacenamiento sigue existiendo. Los page faults, el acceso aleatorio y la presión de memoria pueden dominar el rendimiento.

Mapear un archivo completo para lectura

import mmap

with open("datos.bin", "rb") as archivo:
    with mmap.mmap(
        archivo.fileno(),
        length=0,
        access=mmap.ACCESS_READ,
    ) as memoria:
        print(memoria[:16])

length=0 solicita el tamaño actual en plataformas compatibles. Windows no permite este mapeo para un archivo vacío.

Acceso de solo lectura

ACCESS_READ impide cambios. Una asignación genera TypeError.

memoria[0] = 65  # TypeError

Prefiere este modo para búsquedas y análisis. Reduce el riesgo de corrupción accidental.

Escritura persistente

with open("datos.bin", "r+b") as archivo:
    with mmap.mmap(
        archivo.fileno(),
        0,
        access=mmap.ACCESS_WRITE,
    ) as memoria:
        memoria[0:4] = b"HEAD"
        memoria.flush()

Con ACCESS_WRITE, los cambios afectan al mapeo y al archivo. El slice de reemplazo debe conservar el mismo tamaño.

Copy-on-write

with open("datos.bin", "rb") as archivo:
    with mmap.mmap(
        archivo.fileno(),
        0,
        access=mmap.ACCESS_COPY,
    ) as memoria:
        memoria[0:4] = b"TEST"

Los cambios quedan privados y no actualizan el archivo. Es útil para experimentos, pero no equivale a crear una copia completa por anticipado.

Flush del archivo antes del mapa

Si un archivo escribible contiene cambios en buffers de Python, llama flush() antes de mapear.

archivo.write(b"contenido")
archivo.flush()
memoria = mmap.mmap(archivo.fileno(), 0)

Así los datos locales estarán disponibles para el mapeo.

Buscar bytes

posicion = memoria.find(b"ERROR")
if posicion != -1:
    print("encontrado en", posicion)

find() y rfind() aceptan rangos. El módulo re también puede buscar directamente en mmap.

Expresiones regulares

import re

for match in re.finditer(rb"ID:\d+", memoria):
    print(match.start(), match.group())

Usa patrones de bytes. Interpretar texto exige conocer encoding y límites de caracteres multibyte.

Métodos de archivo

Los objetos tienen posición actual y métodos read(), readline(), seek(), tell() y write().

memoria.seek(0)
primera_linea = memoria.readline()
posicion = memoria.tell()

Desde Python 3.13, seek() devuelve la nueva posición absoluta.

Índices y slices

primero = memoria[0]
cabecera = memoria[0:16]

Asignar un índice requiere un entero de byte. Asignar un slice requiere bytes de longitud compatible.

Persistencia con flush

flush() solicita escribir las páginas modificadas.

memoria.flush()

Se puede indicar offset y tamaño, pero el offset debe alinearse con PAGESIZE o ALLOCATIONGRANULARITY. Maneja excepciones.

Durabilidad no es transacción

Flush del mapa, sincronización del descriptor y consistencia ante crashes son temas relacionados pero distintos. Las aplicaciones transaccionales deben estudiar fsync, orden de escritura y reemplazo atómico.

Mmap no convierte el archivo en base de datos segura automáticamente.

Offsets alineados

El offset del constructor debe ser múltiplo de ALLOCATIONGRANULARITY. Para una región arbitraria, alinea el inicio hacia abajo y conserva un delta.

gran = mmap.ALLOCATIONGRANULARITY
base = inicio // gran * gran
delta = inicio - base
longitud = delta + tamano

Accede luego con memoria[delta:delta+tamano].

Tamaño de archivo y de mapa

La longitud del mapa define la región visible. size() puede devolver el tamaño del archivo, mientras len(memoria) devuelve la región mapeada.

No accedas fuera del límite. Cambios concurrentes del tamaño pueden tener consecuencias graves.

Redimensionar

resize() modifica mapa y archivo cuando corresponde. Los mapas read-only, copy-on-write o con trackfd=False no pueden redimensionarse.

En Windows, otros mapas del mismo archivo pueden bloquear la operación.

trackfd en Unix

Desde Python 3.13, Unix acepta trackfd=False. El descriptor no se duplica, pero size() y resize() dejan de funcionar.

Úsalo solo si el límite de descriptores es un problema real.

Memoria anónima

with mmap.mmap(-1, 4096) as memoria:
    memoria.write(b"datos temporales")

Pasar -1 crea una región no asociada a archivo regular. Puede actuar como buffer o memoria compartida.

Compartir entre procesos

En Unix, un mapa anónimo creado antes de fork() puede compartirse entre padre e hijo. Para código portable, multiprocessing.shared_memory puede ser más explícito.

La memoria compartida no incluye sincronización. Usa locks, semáforos o un protocolo atómico.

MAP_SHARED y MAP_PRIVATE

El constructor Unix permite MAP_SHARED para cambios visibles a otros procesos y MAP_PRIVATE para copy-on-write.

No especifiques access junto con flags y prot.

Diferencias en Windows

Windows acepta tagname para mapas con nombre, pero evitarlo mejora portabilidad. Los offsets deben respetar la granularidad.

Un mapa más largo que el archivo puede extenderlo en Windows. No dependas de esta diferencia sin pruebas.

madvise

En sistemas compatibles, madvise() comunica al kernel el patrón esperado.

if hasattr(memoria, "madvise"):
    memoria.madvise(mmap.MADV_SEQUENTIAL)

Las constantes varían por sistema. Mide el impacto.

Acceso secuencial y aleatorio

El mapeo no elimina la latencia. Los recorridos secuenciales aprovechan prefetch; el acceso aleatorio en archivos mayores que la RAM puede generar muchos page faults.

Haz benchmarks con datos representativos.

Escritores concurrentes

Dos procesos pueden modificar la misma región y romper invariantes. La coherencia de memoria no protege actualizaciones lógicas de varios pasos.

Define versiones, locks, checksums y protocolo de commit.

Truncado externo

Si otro proceso reduce el archivo mapeado, los accesos posteriores pueden fallar de forma grave o dependiente del sistema. Controla el ciclo de vida.

Cerrar recursos

Usa context managers. Cerrar mmap no cierra el objeto de archivo original.

with open("datos.bin", "rb") as archivo:
    with mmap.mmap(archivo.fileno(), 0, access=mmap.ACCESS_READ) as memoria:
        procesar(memoria)

Las vistas de memoria activas pueden impedir el cierre.

Seguridad

Mapear un archivo no valida su contenido. Longitudes, offsets y registros internos pueden ser maliciosos. Comprueba límites antes de calcular slices con valores del archivo.

No mapees dispositivos o archivos especiales sin comprender sus efectos.

Pruebas

Prueba archivos vacíos, pequeños y grandes, mapas de lectura, copy-on-write, regiones alineadas, búsquedas ausentes, flush, concurrencia controlada, Windows y Unix.

Errores frecuentes

  • Mapear un archivo vacío en Windows.
  • Abrir con modo incompatible.
  • Olvidar flush antes del mapeo.
  • Usar offset no alineado.
  • Suponer que flush() ofrece transacción.
  • Asignar slices de tamaño diferente.
  • Redimensionar con otros mapas activos.
  • Compartir memoria sin sincronización.

Buenas prácticas

  • Usa ACCESS_READ por defecto.
  • Usa copy-on-write para cambios temporales.
  • Valida tamaños y offsets.
  • Cierra mapas con with.
  • Mide patrones reales.
  • Sincroniza escritores.
  • Prueba diferencias de plataforma.
  • No trates mmap como base transaccional.

Conclusión

mmap en Python ofrece acceso flexible y eficiente a archivos y regiones de memoria. Combina slices de bytes, métodos de archivo, búsqueda y compartición controlada.

El rendimiento depende del patrón y del sistema operativo. Usa permisos mínimos, alinea offsets, valida estructuras y coordina concurrencia. Consulta la documentación oficial de mmap y el manual mmap de Unix.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código fuente que representa tokens y constantes del parser con el módulo token en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    token en Python: constantes del parser

    Aprende token en Python para interpretar tipos léxicos, operadores exactos, indentación, f-strings, t-strings y parsers por versión.

    Ler mais

    Tempo de leitura: 7 minutos
    07/08/2026
    Código fuente que representa palabras reservadas y soft keywords en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    keyword en Python: palabras reservadas

    Aprende keyword en Python para validar identificadores, palabras reservadas y soft keywords según la versión del intérprete.

    Ler mais

    Tempo de leitura: 7 minutos
    07/08/2026
    Arquitectura de software que representa clases abstractas con abc en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    abc en Python: clases abstractas

    Aprende abc en Python para crear clases abstractas, métodos obligatorios, subclasses virtuales y contratos estables.

    Ler mais

    Tempo de leitura: 5 minutos
    06/08/2026
    Código y estructuras que representan tipos del runtime con el módulo types en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    types en Python: tipos del runtime

    Aprende types en Python para usar SimpleNamespace, MappingProxyType, tipos del runtime y creación dinámica de clases.

    Ler mais

    Tempo de leitura: 5 minutos
    06/08/2026
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    sched en Python: programa eventos

    Aprende sched en Python para programar eventos, controlar prioridades, cancelar tareas y crear recurrencia con reloj monotónico.

    Ler mais

    Tempo de leitura: 7 minutos
    05/08/2026
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    atexit en Python: ejecuta limpieza al salir

    Aprende atexit en Python para ejecutar limpieza al salir, controlar el orden LIFO y evitar problemas con threads, señales y

    Ler mais

    Tempo de leitura: 7 minutos
    05/08/2026