mmap — 메모리 매핑 파일 지원
mmap — 메모리 매핑 파일 지원
메모리 매핑 파일 객체는 bytearray처럼도, 파일 객체처럼도 동작해요. 대부분 bytearray가 필요한 곳에서 mmap 객체를 사용할 수 있어요. 예를 들어 re 모듈로 메모리 매핑 파일을 검색할 수 있어요. 또한 obj[index] = 97처럼 단일 바이트를 바꾸거나, 슬라이스에 할당(obj[i1:i2] = b'...')해서 부분 시퀀스를 바꿀 수도 있어요. 현재 파일 위치에서 데이터를 읽고 쓸 수도 있고, seek()로 파일의 다른 위치로 이동할 수도 있어요.
메모리 매핑 파일은 mmap 생성자로 만들며, Unix와 Windows에서 다르게 동작해요. 어느 쪽이든 업데이트용으로 열린 파일의 파일 디스크립터를 제공해야 해요. 기존 파이썬 파일 객체를 매핑하려면 fileno() 메서드를 사용해 fileno 파라미터의 올바른 값을 구해요. os.open() 함수로 파일을 열 수도 있는데, 이 함수는 파일 디스크립터를 직접 반환해요(파일은 여전히 사용 후 닫아야 함).
쓰기 가능한 버퍼 파일에 대한 메모리 매핑을 만들려면 먼저 파일을 flush()해야 해요. 이는 버퍼의 로컬 수정 사항이 실제로 매핑에 사용 가능하도록 하는 데 필요해요. 이 모듈은 WASI에서 동작하지 않거나 사용할 수 없어요.
본문
생성자
class mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT, offset=0) (Windows 버전) — 파일 핸들 fileno가 지정한 파일에서 length 바이트를 매핑하고 mmap 객체를 만들어요. length가 파일의 현재 크기보다 크면 파일이 length 바이트를 포함하도록 확장돼요. length가 0이면 맵의 최대 길이는 파일의 현재 크기이며, 단 파일이 비어 있으면 Windows가 예외를 발생시켜요(Windows에서는 빈 매핑을 만들 수 없음).
tagname은 지정하면 None이 아닌, 매핑에 대한 태그 이름을 주는 문자열이에요. Windows는 같은 파일에 대해 여러 다른 매핑을 가질 수 있게 해줘요. 기존 태그 이름을 지정하면 그 태그가 열리고, 그렇지 않으면 새 태그가 만들어져요. 이 파라미터를 생략하거나 None으로 두면 매핑이 이름 없이 만들어져요. tagname 사용을 피하면 코드를 Unix와 Windows 간에 이식 가능하게 유지하는 데 도움이 돼요.
offset은 음이 아닌 정수 오프셋으로 지정할 수 있어요. mmap 참조는 파일 시작에서부터의 오프셋과 상대적이에요. offset 기본값은 0이며 ALLOCATIONGRANULARITY의 배수여야 해요.
class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE | PROT_READ, access=ACCESS_DEFAULT, offset=0, *, trackfd=True) (Unix 버전) — 파일 디스크립터 fileno가 지정한 파일에서 length 바이트를 매핑하고 mmap 객체를 반환해요. length가 0이면 맵의 최대 길이는 mmap을 호출할 때의 파일 현재 크기가 돼요.
flags는 매핑의 본질을 지정해요. MAP_PRIVATE는 비공개 copy-on-write 매핑을 만들어 mmap 객체 내용의 변경이 이 프로세스에 비공개가 되게 하고, MAP_SHARED는 파일의 같은 영역을 매핑하는 모든 다른 프로세스와 공유되는 매핑을 만들어요. 기본값은 MAP_SHARED예요. prot은 지정하면 원하는 메모리 보호를 주며, 가장 유용한 값은 페이지를 읽거나 쓸 수 있다는 것을 지정하는 PROT_READ와 PROT_WRITE예요. prot 기본값은 PROT_READ | PROT_WRITE예요. access는 flags와 prot 대신 선택적 키워드 파라미터로 지정할 수 있으며, flags, prot, access를 모두 지정하는 것은 오류예요.
trackfd가 False이면 fileno로 지정된 파일 디스크립터가 복제되지 않고, 결과 mmap 객체가 맵의 기반 파일과 연결되지 않아 size()와 resize() 메서드가 실패해요. 이 모드는 열린 파일 디스크립터 수를 제한하는 데 유용해요.
access는 네 가지 값 중 하나를 받아요: ACCESS_READ(읽기 전용), ACCESS_WRITE(write-through), ACCESS_COPY(copy-on-write), ACCESS_DEFAULT(prot에 위임). access가 지정되지 않으면 Windows mmap은 write-through 매핑을 반환해요. ACCESS_READ 메모리 맵에 할당하면 TypeError가, ACCESS_WRITE 메모리 맵에 할당하면 메모리와 기반 파일에 모두 영향을 미치고, ACCESS_COPY 메모리 맵에 할당하면 메모리에는 영향을 미치지만 기반 파일은 업데이트하지 않아요.
익명 메모리를 매핑하려면 fileno로 -1을, 길이와 함께 전달해요.
간단한 사용 예시:
import mmap
with open("hello.txt", "wb") as f:
f.write(b"Hello Python!\n")
with open("hello.txt", "r+b") as f:
mm = mmap.mmap(f.fileno(), 0)
print(mm.readline()) # prints b"Hello Python!\n"
print(mm[:5]) # prints b"Hello"
mm[6:] = b" world!\n"
mm.seek(0)
print(mm.readline()) # prints b"Hello world!\n"
mm.close()
mmap은 with 문에서 컨텍스트 매니저로도 사용할 수 있어요:
import mmap
with mmap.mmap(-1, 13) as mm:
mm.write(b"Hello world!")
메서드
close() — mmap을 닫아요. 이후 객체의 다른 메서드 호출은 ValueError 예외를 발생시켜요. 열린 파일은 닫지 않아요.
closed — 파일이 닫혀 있으면 True.
find(sub[, start[, end]]) — 서브시퀀스 sub가 범위 [start, end]에 포함되도록 발견되는 객체의 최저 인덱스를 반환해요. 실패하면 -1을 반환해요.
flush(), flush(offset, size, /) — 파일의 메모리 내 사본에 대한 변경을 디스크에 다시 기록해요. offset과 size를 지정하면 주어진 바이트 범위의 변경만 디스크에 기록되고, 그렇지 않으면 매핑의 전체 범위가 기록돼요. offset은 PAGESIZE 또는 ALLOCATIONGRANULARITY의 배수여야 해요. 성공하면 None이 반환되고, 실패하면 예외가 발생해요.
madvise(option[, start[, length]]) — start에서 시작해 length 바이트만큼 확장되는 메모리 영역에 대해 커널에 조언 옵션 option을 보내요. option은 시스템에서 사용 가능한 MADV_* 상수 중 하나여야 해요. 버전 3.8에서 추가됨.
move(dest, src, count) — 오프셋 src에서 시작하는 count 바이트를 대상 인덱스 dest로 복사해요.
read([n]) — 현재 파일 위치에서 시작해 최대 n 바이트를 포함하는 bytes를 반환해요. 인자가 생략되거나 None 또는 음수이면 현재 파일 위치에서 매핑 끝까지의 모든 바이트를 반환해요.
read_byte() — 현재 파일 위치의 바이트를 정수로 반환하고 파일 위치를 1만큼 전진시켜요.
readline() — 현재 파일 위치에서 시작해 다음 줄 바꿈까지의 단일 줄을 반환해요.
resize(newsize) — 맵과 기반 파일(있는 경우)의 크기를 조정해요. ACCESS_READ 또는 ACCESS_COPY access로 만든 맵의 크기를 조정하면 TypeError가, trackfd를 False로 설정해 만든 맵의 크기를 조정하면 ValueError가 발생해요. Windows에서 다른 맵이 같은 이름의 파일에 대해 있으면 OSError가 발생해요.
rfind(sub[, start[, end]]) — 서브시퀀스 sub가 범위 [start, end]에 포함되도록 발견되는 객체의 최고 인덱스를 반환해요. 실패하면 -1을 반환해요.
seek(pos[, whence]) — 파일의 현재 위치를 설정해요. whence의 기본값은 os.SEEK_SET 또는 0(절대 파일 위치)이며, os.SEEK_CUR 또는 1(현재 위치 기준), os.SEEK_END 또는 2(파일 끝 기준)도 있어요. 버전 3.13에서 변경: None 대신 새 절대 위치를 반환.
seekable() — 파일이 시크를 지원하는지 반환하며, 반환값은 항상 True. 버전 3.13에서 추가됨.
size() — 메모리 매핑 영역의 크기보다 클 수 있는 파일의 길이를 반환해요.
tell() — 파일 포인터의 현재 위치를 반환해요.
write(bytes) — 파일 포인터의 현재 위치에서 bytes를 메모리에 쓰고 쓴 바이트 수를 반환해요. 파일 위치는 쓰인 바이트 뒤를 가리키도록 갱신돼요. ACCESS_READ로 만든 mmap에 쓰면 TypeError가 발생해요.
write_byte(byte) — 파일 포인터의 현재 위치에서 정수 byte를 메모리에 쓰고 파일 위치를 1만큼 전진시켜요. ACCESS_READ로 만든 mmap에 쓰면 TypeError가 발생해요.
MADV_* 상수
mmap.MADV_NORMAL, mmap.MADV_RANDOM, mmap.MADV_SEQUENTIAL, mmap.MADV_WILLNEED, mmap.MADV_DONTNEED, mmap.MADV_REMOVE, mmap.MADV_DONTFORK, mmap.MADV_DOFORK, mmap.MADV_HWPOISON, mmap.MADV_MERGEABLE 등. 이 옵션들은 mmap.madvise()에 전달할 수 있어요. 모든 옵션이 모든 시스템에 존재하는 것은 아니에요.
MAP_* 상수
mmap.MAP_SHARED, mmap.MAP_PRIVATE, mmap.MAP_32BIT, mmap.MAP_ALIGNED_SUPER, mmap.MAP_ANON, mmap.MAP_ANONYMOUS, mmap.MAP_CONCEAL, mmap.MAP_DENYWRITE 등. 이들은 mmap.mmap()에 전달할 수 있는 다양한 플래그예요. MAP_ALIGNED_SUPER는 FreeBSD에서만, MAP_CONCEAL은 OpenBSD에서만 사용할 수 있으며, 일부 옵션은 일부 시스템에 없을 수 있어요.