[Изменить: эта проблема относится только к 32-разрядным системам. Если ваш компьютер, ваша ОС и ваша реализация на python 64-битные, то создание больших файлов работает надежно и чрезвычайно эффективно.]
Я пишу модуль, который, помимо прочего, предоставляет побитовый доступ для чтения к файлам. Файлы могут быть большими (сотни ГБ), поэтому я написал простой класс, который позволяет мне обрабатывать файл как строку и скрывает все операции поиска и чтения.
В то время, когда я писал свой класс-оболочку, я не знал о модуле mmap . Читая документацию для mmap, я подумал "отлично - это как раз то, что мне нужно, я возьму свой код и заменю его на mmap. Возможно, он гораздо эффективнее и всегда хорошо удалять код".
Проблема в том, что mmap не работает с большими файлами! Это очень удивительно для меня, так как я думал, что это, пожалуй, самое очевидное приложение. Если размер файла превышает несколько гигабайт, я получаю EnvironmentError: [Errno 12] Cannot allocate memory
. Это происходит только с 32-битной сборкой Python, поэтому кажется, что она исчерпывает адресное пространство, но я не могу найти никакой документации по этому вопросу.
Мой код просто
f = open('somelargefile', 'rb')
map = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
Итак, мой вопрос Я что-то упускаю здесь очевидное? Есть ли способ заставить mmap работать с большими файлами или я должен вернуться к своей наивной оболочке для файлов?
Обновление. Похоже, что у карты Python mmap должны быть те же ограничения, что и у карты POSIX. Чтобы лучше выразить свое недовольство, приведу простой класс, который имеет небольшую часть функциональности mmap.
import os
class Mmap(object):
def __init__(self, f):
"""Initialise with a file object."""
self.source = f
def __getitem__(self, key):
try:
# A slice
self.source.seek(key.start, os.SEEK_SET)
return self.source.read(key.stop - key.start)
except AttributeError:
# single element
self.source.seek(key, os.SEEK_SET)
return self.source.read(1)
Это только для чтения и не делает ничего особенного, но я могу сделать это так же, как с mmap:
map2 = Mmap(f)
print map2[0:10]
print map2[10000000000:10000000010]
за исключением того, что нет никаких ограничений на размер файла. Не слишком сложно на самом деле ...