16.5. 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 должен быть кратен PAGESIZE или ALLOCATIONGRANULARITY.
Для обеспечения корректности созданного отображения в память файл, заданный дескриптором 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("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.close()¶
Закрывает файл. Последующие вызовы других методов объекта приведут к возникновению исключения.
- mmap.closed¶
True, если файл закрыт.
Новое в версии 3.2.
- mmap.find(sub[, start[, end]])¶
Возвращает наименьший индекс в объекте, где встречается подпоследовательность sub, при условии, что sub содержится в диапазоне [start, end]. Необязательные аргументы start и end интерпретируются как в записи среза. В случае неудачи возвращает -1.
- mmap.flush([offset[, size]])¶
Сбрасывает изменения, внесённые в копию файла в памяти, обратно на диск. Без вызова этого метода нет гарантии, что изменения будут записаны до уничтожения объекта. Если указаны offset и size, на диск будут сброшены только изменения в заданном диапазоне байтов; в противном случае сбрасывается вся область отображения.
(версия Windows) Ненулевое возвращённое значение означает успех; нулевое – неудачу.
(версия Unix) Возвращается нулевое значение, означающее успех. При ошибке вызова возбуждается исключение.
- mmap.move(dest, src, count)¶
Копирует count байт, начиная со смещения src, в целевой индекс dest. Если mmap был создан с ACCESS_READ, то вызовы move приведут к исключению TypeError.
- mmap.read(num)¶
Возвращает объект bytes, содержащий до num байт, начиная с текущей позиции в файле; позиция файла обновляется и указывает на байты, следующие за возвращёнными.
- mmap.read_byte()¶
Возвращает байт в текущей позиции файла в виде целого числа и увеличивает позицию файла на 1.
- mmap.readline()¶
Возвращает одну строку, начиная с текущей позиции в файле и до следующего символа новой строки.
- mmap.resize(newsize)¶
Изменяет размер отображения и базового файла (если он есть). Если mmap был создан с ACCESS_READ или ACCESS_COPY, изменение размера вызовет исключение TypeError.
- mmap.rfind(sub[, start[, end]])¶
Возвращает наибольший индекс в объекте, где найдена подпоследовательность sub, такой, что sub содержится в диапазоне [start, end]. Необязательные аргументы start и end интерпретируются как в нотации среза. Возвращает -1 при неудаче.
- mmap.seek(pos[, whence])¶
Устанавливает текущую позицию файла. Аргумент whence является необязательным и по умолчанию равен os.SEEK_SET или 0 (абсолютное позиционирование); другие значения: os.SEEK_CUR или 1 (смещение относительно текущей позиции) и os.SEEK_END или 2 (смещение относительно конца файла).
- mmap.size()¶
Возвращает длину файла, которая может быть больше размера области отображения памяти.
- mmap.tell()¶
Возвращает текущую позицию файлового указателя.