24

I have a really large file I'm trying to open with mmap and its giving me permission denied. I've tried different flags and modes to the os.open but its just not working for me.

What am I doing wrong?

>>> 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
>>> 

(using the built in open() works via the python docs example, but it seems to open more than one handle to the file both in read & write mode. All i need for the mmap.mmap method is the file number, so I wouldn't assume i need to create a file object; hence my attempt at using os.open())

tshepang
  • 12,111
  • 21
  • 91
  • 136
tMC
  • 18,105
  • 14
  • 62
  • 98
  • Silly question, but do you have read permission on the file? – reve_etrange Jun 08 '11 at 23:51
  • Why'd you open the file via `os.open` rather than the builtin `open()`? Size? For ~50 MB files (may be small relative to you) that I scanned through with re, the builtin worked fine for me after incorporating `prot=mmap.PROT_READ` as per Bobby. – Nick T Apr 20 '13 at 00:29

4 Answers4

43

I think its a flags issue, try opening as read only:

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

and mmap.mmap by default tries to map read/write, so just map read only:

mfile = mmap.mmap(mfd, 0, prot=mmap.PROT_READ)
Sam Mussmann
  • 5,883
  • 2
  • 29
  • 43
Bobby Powers
  • 2,863
  • 23
  • 15
  • 3
    By default os.open() opens the file as read-only, so you don't need the "os.O_RDONLY". The important thing is the "prot=mmap.PROT_READ", since you cannot memory-map a file with write permissions, if the file has been opened with read-only permissions. – Seppo Enarvi Mar 25 '13 at 12:24
  • @senarvi - the python 2 docs say 'The default mode is 0777 (octal), and the current umask value is first masked out' - http://docs.python.org/2/library/os.html#os.open , so whether the file gets open RO or RW seems dependent on your umask if you omit the mode. – Bobby Powers Apr 06 '13 at 19:40
  • Oh you're right. I didn't notice that we're not using the built-in open(). – Seppo Enarvi Apr 08 '13 at 10:52
12

Try setting the file mode to r+. That worked for me on Linux:

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

Then this worked for me as normal:

mfile = mmap.mmap(mfd, 0)
Chris Laplante
  • 29,338
  • 17
  • 103
  • 134
6

In my case this error occurred because I was attempting to open a block device without specifying an explicit size.

FWIW you cannot use os.stat / os.fstat with a block device to obtain the device's size (which is always 0), but you can use file.seek and 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)
RobM
  • 8,373
  • 3
  • 45
  • 37
  • Do you mean `f = open("/dev/loop0", "rb")` and `size = f.tell()`? – davidA Mar 15 '18 at 01:45
  • Oops, yes it should be `size = f.tell()` I'll fix that. As for `file()` versus `open()`, in Python2 `file()` is valid and I slightly prefer it over `open()` so I'll leave it be. – RobM Mar 20 '18 at 00:11
2

The cross-platform call of mmap can be performed using access parameter:

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

The mmap construction permissions should be synced with the file open permissions (both read, write, or read/write).

luart
  • 1,383
  • 1
  • 18
  • 25