Python mmap «Отказано в доступе» в Linux

У меня есть действительно большой файл, который я пытаюсь открыть с помощью mmap, и мне отказывают в доступе. Я пробовал разные флаги и режимы для os.open, но у меня это просто не работает.

Что я делаю не так?

>>> import os,mmap
>>> mfd = os.open('BigFile', 0)
>>> mfile = mmap.mmap(mfd, 0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
mmap.error: [Errno 13] Permission denied
>>> 

(использование встроенного open() работает через пример документации python, но, похоже, он открывает более одного дескриптора файла как в режиме чтения, так и в режиме записи. Все, что мне нужно для метода mmap.mmap, это номер файла, поэтому я бы не стал предполагать мне нужно создать объект file, отсюда и моя попытка использовать os.open())


person tMC    schedule 08.06.2011    source источник
comment
Глупый вопрос, а у вас есть разрешение на чтение файла?   -  person reve_etrange    schedule 09.06.2011
comment
Почему вы открыли файл через os.open, а не через встроенный open()? Размер? Для файлов ~ 50 МБ (может быть небольшим по сравнению с вами), которые я сканировал с помощью re, встроенная функция работала нормально для меня после включения prot=mmap.PROT_READ согласно Бобби.   -  person Nick T    schedule 20.04.2013


Ответы (4)


Я думаю, что это проблема с флагами, попробуйте открыть только для чтения:

mfd = os.open('BigFile', os.O_RDONLY)

а mmap.mmap по умолчанию пытается сопоставить чтение/запись, поэтому просто сопоставьте только чтение:

mfile = mmap.mmap(mfd, 0, prot=mmap.PROT_READ)
person Bobby Powers    schedule 08.06.2011
comment
По умолчанию os.open() открывает файл только для чтения, поэтому вам не нужен os.O_RDONLY. Важно то, что prot=mmap.PROT_READ, так как вы не можете отобразить в память файл с разрешениями на запись, если файл был открыт с разрешениями только на чтение. - person Seppo Enarvi; 25.03.2013
comment
@senarvi - документы python 2 говорят: «Режим по умолчанию — 0777 (восьмеричный), а текущее значение umask сначала маскируется» — docs.python.org/2/library/os.html#os.open , поэтому, будет ли файл открыт RO или RW, похоже, зависит от вашего umask, если вы опускаете режим. - person Bobby Powers; 06.04.2013
comment
О, ты прав. Я не заметил, что мы не используем встроенную функцию open(). - person Seppo Enarvi; 08.04.2013

Попробуйте установить режим файла r+. Это сработало для меня в Linux:

mfd = os.open('BigFile', "r+")

Тогда это работало для меня как обычно:

mfile = mmap.mmap(mfd, 0)
person Chris Laplante    schedule 19.01.2013
comment
Я пытался open('foo.txt', 'rwb'). Спасибо за спасение моего здравомыслия. - person Jonathon Reinhart; 09.10.2015
comment
@ДжонатонРейнхарт; пожалуйста! Флаги не имеют для меня никакого смысла - person Chris Laplante; 10.10.2015

В моем случае эта ошибка произошла из-за того, что я пытался открыть блочное устройство без явного указания размера.

FWIW вы не можете использовать os.stat / os.fstat с блочным устройством для получения размера устройства (который всегда равен 0), но вы можете использовать file.seek и file.tell:

f = file("/dev/loop0", "rb")
f.seek(0, 2)  # Seek relative to end of file
size = f.tell()
fh = f.fileno()

m = mmap.mmap(f, size, mmap.MAP_PRIVATE, mmap.PROT_READ)
person RobM    schedule 11.02.2012
comment
Вы имеете в виду f = open("/dev/loop0", "rb") и size = f.tell()? - person davidA; 15.03.2018
comment
К сожалению, да, это должно быть size = f.tell(), я это исправлю. Что касается file() по сравнению с open(), в Python2 допустимо file(), и я немного предпочитаю его open(), поэтому я оставлю его. - person RobM; 20.03.2018

Кросс-платформенный вызов mmap можно выполнить с помощью параметра access:

mfd = os.open('BigFile', os.O_RDONLY)
mm = mmap.mmap(mfd, 0, access=mmap.ACCESS_READ)

Разрешения на построение mmap должны быть синхронизированы с разрешениями на открытие файла (как на чтение, так и на запись или чтение/запись).

person luart    schedule 01.01.2016