mmap — Поддержка отображаемых в память файлов


Отображаемые в память файловые объекты, ведут себя аналогично bytearray и файловым объектам. Вы можете использовать объекты mmap в большинстве мест, где ожидается bytearray; например, вы можете использовать модуль re для поиска в отображённом в памяти файле. Вы также можете изменить один байт, выполнив obj[index] = 97, или изменить подпоследовательность, назначив слайсу: obj[i1:i2] = b'...'. Вы также можете читать и записывать данные, начиная с текущей позиции файла, и seek() через файл в разные позиции.

Файл с отображением в памяти создаётся конструктором mmap, который отличается в Unix и Windows. В любом случае вы должны указать файловый дескриптор для файла, открытого для обновления. Если вы хотите сопоставить существующий файловый объект Python, используйте метод fileno(), чтобы получить правильное значение для параметра fileno. В противном случае вы можете открыть файл с помощью функции os.open(), которая возвращает дескриптор файла напрямую (по завершении файл всё равно должен быть закрыт).

Примечание

Если вы хотите создать отображение памяти для доступного для записи буферизованного файла, вы должны выполнить flush() файла. Это необходимо для того, чтобы локальные модификации буферов действительно были доступны для отображения.

Для версий конструктора как для Unix, так и для Windows access может быть указан как необязательный ключевой параметр. access принимает одно из четырёх значений: ACCESS_READ, ACCESS_WRITE или ACCESS_COPY, чтобы указать память только для чтения, сквозной записи или копирования при записи соответственно, или ACCESS_DEFAULT, чтобы отложить до prot. access можно использовать как в Unix, так и в Windows. Если access не указан, Windows mmap возвращает отображение со сквозной записью. Начальные значения памяти для всех трёх типов доступа берутся из указанного файла. Присвоение отображению памяти ACCESS_READ вызывает исключение TypeError. Назначение отображения памяти ACCESS_WRITE влияет как на память, так и на базовый файл. Назначение отображения памяти ACCESS_COPY влияет на память, но не обновляет базовый файл.

Изменено в версии 3.7: Добавлена константа ACCESS_DEFAULT.

Чтобы отобразить анонимную память, в качестве номера файла вместе с длиной следует передать -1.

class mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])

(Версия для Windows) Сопоставляет length байтов из файла, указанного дескриптором файла fileno, и создаёт mmap объект. Если length больше текущего размера файла, файл расширяется до length байт. Если length равен 0, максимальная длина отображения равна текущему размеру файла, за исключением случая, когда файл пуст, Windows вызывает исключение (вы не можете создать пустое отображение в Windows).

Если указан tagname и он не None, представляет собой строку, задающую имя тега для отображения. Windows позволяет вам иметь много разных отображений с одним и тем же файлом. Если вы указываете имя существующего тега, то данный тег открывается, в противном случае создаётся новый тег с данным именем. Если данный параметр пропущен или None, отображение создаётся без имени. Отказ от использования параметра тега поможет обеспечить переносимость вашего кода между Unix и Windows.

offset может быть указан как неотрицательное целочисленное смещение. Ссылки mmap будут относиться к смещению от начала файла. offset по умолчанию равен 0. offset должен быть кратен ALLOCATIONGRANULARITY.

Вызывает событие аудита mmap.__new__ с аргументами fileno, length, access, offset.

class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT[, offset])

(Версия для Unix) Сопоставляет length байтов из файла, указанного файловым дескриптором fileno, и возвращает mmap объект. Если length равен 0, максимальная длина отображения будет равна текущему размеру файла при вызове mmap.

flags определяет характер отображения. MAP_PRIVATE создаёт частное отображение копирования при записи, поэтому изменения содержимого объекта mmap будут частными для этого процесса, а MAP_SHARED создаёт совместно используемое всеми другими процессами отображение, сопоставляющими те же области файла. Значение по умолчанию — MAP_SHARED.

Если указан prot, предоставляет желаемую защиту памяти; два наиболее полезных значения: PROT_READ и PROT_WRITE, чтобы указать, что страницы могут быть прочитаны или записаны. prot по умолчанию PROT_READ | PROT_WRITE.

access можно указать вместо flags и prot в качестве необязательного ключевого параметра. Ошибка указывать оба flags, prot и access. См. описание access выше для получения информации о том, как использовать данный параметр.

offset может быть указан как неотрицательное целочисленное смещение. Mmap ссылки будут относиться к смещению от начала файла. offset по умолчанию равен 0. offset должен быть кратным ALLOCATIONGRANULARITY, который равен PAGESIZE в Unix системах.

Чтобы обеспечить достоверность созданного отображения памяти, указанный дескриптором fileno файл, автоматически синхронизируется внутри с физическим резервным хранилищем (physical backing store) в Mac OS X и OpenVMS.

В этом примере показан простой способ использования mmap:

import mmap

# записываем простой пример файла
with open("hello.txt", "wb") as f:
    f.write(b"Hello Python!\n")

with open("hello.txt", "r+b") as f:
    # отображение памяти файла, размер 0 означает весь файл
    mm = mmap.mmap(f.fileno(), 0)
    # читаем содержимое стандартными файловыми методами
    print(mm.readline())  # распечатает b"Hello Python!\n"
    # читаем содержимое через нотацию среза
    print(mm[:5])  # распечатает b"Hello"
    # обновляем содержимое, используя нотацию среза;
    # обратите внимание, что новый контент должен иметь такой же размер
    mm[6:] = b" world!\n"
    # ... и читаем снова, используя стандартные файловые методы
    mm.seek(0)
    print(mm.readline())  # распечатает  b"Hello Python!\n"
    # закрываем отображение
    mm.close()

mmap также может использоваться в качестве менеджера контекста в операторе with:

import mmap

with mmap.mmap(-1, 13) as mm:
    mm.write(b"Hello world!")

Добавлено в версии 3.2: Поддержка контекстного менеджера.

В следующем примере показано, как создать анонимное отображение и обмениваться данными между родительским и дочерним процессами:

import mmap
import os

mm = mmap.mmap(-1, 13)
mm.write(b"Hello world!")

pid = os.fork()

if pid == 0:  # В дочернем процессе
    mm.seek(0)
    print(mm.readline())

    mm.close()

Вызывает событие аудита mmap.__new__ с аргументами fileno, length, access, offset.

Файловые объекты, отображаемые в памяти, поддерживают следующие методы:

close()

Закрывает mmap. Последующие вызовы других методов объекта приведут к возникновению исключения ValueError. Это не закроет открытый файл.

closed

True, если файл закрыт.

Добавлено в версии 3.2.

find(sub[, start[, end]])

Возвращает наименьший индекс в объекте, где найдена подпоследовательность sub, так что sub содержится в диапазоне [start, end]. Необязательные аргументы start и end интерпретируются как в нотации среза. Возвращает -1 в случае ошибки.

Изменено в версии 3.5: Доступен для записи байтоподобный объект.

flush([offset[, size]])

Сбрасывает изменения, внесённые в копию файла в памяти, обратно на диск. Без использования данного вызова нет гарантии, что изменения будут записаны обратно до того, как объект будет уничтожен. Если указаны offset и size, на диск будут сброшены только изменения в указанном диапазоне байтов; в противном случае сбрасывается весь экстент отображения. offset должен быть кратен PAGESIZE или ALLOCATIONGRANULARITY.

Возвращается None, для указания успешности. Исключение возникает при сбое вызова.

Изменено в версии 3.8: Ранее в случае успеха возвращалось ненулевое значение; ноль возвращался при ошибке в Windows. В случае успеха было возвращено нулевое значение; исключение возникло при ошибке в Unix.

madvise(option[, start[, length]])

Отправляет ядру совет (advise) option об области памяти, начинающейся с start и расширяющейся на length байт. option должен быть одним из MADV_* констант, доступных в системе. Если start и length пропущены, охватывается всё отображение. В некоторых системах (включая Linux) start должен быть кратен PAGESIZE.

Доступность: системы с системным вызовом madvise().

Добавлено в версии 3.8.

move(dest, src, count)

Скопировать count байт, начиная со смещения src, в целевой индекс dest. Если mmap был создан с ACCESS_READ, то вызов Move вызовут исключение TypeError.

read([n])

Возвращает bytes, содержащий до n байт, начиная с текущей позиции в файле. Если аргумент пропущен, None или отрицательный, возвращаются все байты от текущей позиции файла до конца отображения. Позиция в файле обновляется так, чтобы она указывала после возвращённых байтов.

Изменено в версии 3.3: Аргумент может быть пропущен или None.

read_byte()

Возвращает байт в текущей позиции файла как целое число и перемещает позицию файла на 1.

readline()

Возвращает одну строку, начиная с текущей позиции файла и до следующей новой строки.

resize(newsize)

Изменяет размер отображения и базового файла, если он есть. Если mmap был создан с ACCESS_READ или ACCESS_COPY, изменение размера отображения вызовет исключение TypeError.

rfind(sub[, start[, end]])

Возвращает самый высокий индекс в объекте, где найдена подпоследовательность sub, так что sub содержится в диапазоне [start, end]. Необязательные аргументы start и end интерпретируются как в нотации среза. Возвращает -1 в случае ошибки.

Изменено в версии 3.5: Доступен для записи байтоподобный объект.

seek(pos[, whence])

Устанавливает текущую позицию файла. Аргумент whence является необязательным и по умолчанию равен os.SEEK_SET или 0 (абсолютное позиционирование файла); другие значения: os.SEEK_CUR или 1 (поиск относительно текущей позиции) и os.SEEK_END или 2 (поиск относительно конца файла).

size()

Возвращает длину файла, которая может быть больше, чем размер отображаемой в памяти области.

tell()

Возвращает текущую позицию указателя файла.

write(bytes)

Записывает bytes байты в память в текущей позиции указателя файла и возвращает количество записанных байтов (никогда не меньше len(bytes), поскольку в случае сбоя записи будет вызвано ValueError). Позиция в файле обновляется так, чтобы она указывала после записанных байтов. Если mmap был создан с ACCESS_READ, то запись в него вызовет исключение TypeError.

Изменено в версии 3.5: Доступен для записи байтоподобный объект.

Изменено в версии 3.6: Теперь возвращается количество записанных байтов.

write_byte(byte)

Записывает целое число byte в память в текущей позиции указателя файла; позиция в файле увеличивается на 1. Если mmap был создан с ACCESS_READ, то запись в него вызовет исключение TypeError.

Константы MADV_*

mmap.MADV_NORMAL
mmap.MADV_RANDOM
mmap.MADV_SEQUENTIAL
mmap.MADV_WILLNEED
mmap.MADV_DONTNEED
mmap.MADV_REMOVE
mmap.MADV_DONTFORK
mmap.MADV_DOFORK
mmap.MADV_HWPOISON
mmap.MADV_MERGEABLE
mmap.MADV_UNMERGEABLE
mmap.MADV_SOFT_OFFLINE
mmap.MADV_HUGEPAGE
mmap.MADV_NOHUGEPAGE
mmap.MADV_DONTDUMP
mmap.MADV_DODUMP
mmap.MADV_FREE
mmap.MADV_NOSYNC
mmap.MADV_AUTOSYNC
mmap.MADV_NOCORE
mmap.MADV_CORE
mmap.MADV_PROTECT

Данные параметры можно передать в mmap.madvise(). Не каждая опция будет присутствовать в каждой системе.

Доступность: системы с системным вызовом madvise().

Добавлено в версии 3.8.