Документация Python неофициальный перевод

18.9. mmap – Поддержка отображаемых в память файловmmap – Memory-mapped file support


Объекты файлов с отображением в память ведут себя и как 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 можно использовать и в Unix, и в Windows. Если access не указан, Windows mmap создаёт отображение со сквозной записью. Начальные значения памяти для всех трёх типов доступа берутся из указанного файла. Присваивание отображаемой в память области с доступом ACCESS_READ вызывает исключение TypeError. Присваивание области с доступом ACCESS_WRITE затрагивает как память, так и нижележащий файл. Присваивание области с доступом ACCESS_COPY затрагивает память, но не обновляет нижележащий файл.

Для отображения анонимной памяти в качестве fileno следует передать -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, отображение создаётся без имени. Отказ от использования параметра tag поможет сохранить переносимость кода между Unix и Windows.

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

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, что в системах Unix равно PAGESIZE.

Для обеспечения корректности созданного отображения в память файл, заданный дескриптором fileno, внутренне автоматически синхронизируется с физическим хранилищем на 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  world!\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()

Объекты файлов с отображением в память поддерживают следующие методы:

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.

(версия Windows) Ненулевое возвращённое значение означает успех; нулевое – неудачу.

(версия Unix) Возвращается нулевое значение, означающее успех. При ошибке вызова возбуждается исключение.

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.