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 должен быть кратен 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(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, на диск будут сброшены только изменения в заданном диапазоне байтов; в противном случае сбрасывается вся область отображения.
(версия 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 в память в текущую позицию файлового указателя; позиция файла обновляется так, чтобы указывать после записанных байтов. Если mmap был создан с
ACCESS_READ, то запись в него вызовет исключениеTypeError.Изменено в версии 3.5: Теперь принимается записываемый байтоподобный объект.
-