"mmap" --- 메모리 맵 파일 지원
******************************

======================================================================

메모리 맵 파일 객체는 동시에 "bytearray" 와 *파일 객체*처럼 작동합니다
. "bytearray"를 기대하는 대부분 장소에서 mmap 객체를 사용할 수 있습니
다. 예를 들어, "re" 모듈을 사용하여 메모리 맵 파일을 검색할 수 있습니
다. "obj[index] = 97"를 사용해서 한 바이트를 변경하거나, 슬라이스에 대
입하여 서브 시퀀스를 변경할 수도 있습니다: "obj[i1:i2] = b'...'". 또한
현재 파일 위치에서 시작하여 데이터를 읽고 쓸 수 있고, 다른 위치로 파일
을 "seek()" 할 수 있습니다.

메모리 맵 파일은 "mmap" 생성자로 만드는데, 유닉스와 윈도우에서 다릅니
다. 두 경우 모두 갱신을 위해 열린 파일에 대한 파일 기술자를 제공해야
합니다. 기존 파이썬 파일 객체를 매핑하려면, "fileno()" 메서드를 사용하
여 *fileno* 매개 변수에 대한 올바른 값을 가져오십시오. 그렇지 않으면,
파일 기술자를 직접 반환하는 "os.open()" 함수를 사용하여 파일을 열 수
있습니다 (완료되면 파일을 닫아야 합니다).

참고:

  쓰기 가능하고 버퍼링 되는 파일에 대한 메모리 맵을 만들려면, 먼저 파
  일을 "flush()"해야 합니다. 버퍼에 대한 지역 변경 사항이 실제로 매핑
  에 반영되게 하는 데 필요합니다.

유닉스와 윈도우 버전의 생성자 모두에서, *access*는 선택적 키워드 매개
변수로 지정될 수 있습니다. *access*는 "ACCESS_READ", "ACCESS_WRITE" 또
는 "ACCESS_COPY" 중 하나의 값을 받아, 읽기 전용, 동시 기록(write-
through) 또는 쓸 때 복사(copy-on-write) 메모리를 각각 지정하거나,
"ACCESS_DEFAULT"를 사용하여 *prot*로 위임합니다. *access*는 유닉스와
윈도우에서 모두 사용할 수 있습니다. *access*를 지정하지 않으면, 윈도우
mmap은 동시 기록(write-through) 매핑을 반환합니다. 세 가지 액세스 유형
모두에서 초기 메모리값은 지정된 파일에서 가져옵니다. "ACCESS_READ" 메
모리 맵에 대입하면 "TypeError" 예외가 발생합니다. "ACCESS_WRITE" 메모
리 맵에 대입하면 메모리와 하부 파일에 모두 영향을 줍니다.
"ACCESS_COPY" 메모리 맵에 대입하면 메모리에는 영향을 미치지만, 하부 파
일은 변경되지 않습니다.

버전 3.7에서 변경: "ACCESS_DEFAULT" 상수가 추가되었습니다.

익명 메모리를 매핑하려면, length와 함께 -1을 fileno로 전달해야 합니다.

class mmap.mmap(fileno, length, tagname=None, access=ACCESS_DEFAULT[, offset])

   **(윈도우 버전)** 파일 핸들 *fileno*로 지정된 파일의 *length* 바이
   트를 매핑하고, mmap 객체를 만듭니다. *length*가 파일의 현재 크기보
   다 크면, 파일은 *length* 바이트를 포함하도록 확장됩니다. *length*가
   "0" 이면, 맵의 최대 길이는 파일의 현재 길이입니다. 단, 파일이 비어
   있으면 윈도우에서 예외가 발생합니다 (윈도우에는 빈 매핑을 만들 수
   없습니다).

   *tagname*가 지정되고 "None"이 아니면, 매핑의 태그 이름을 제공하는
   문자열입니다. 윈도우에서는 같은 파일에 대해 여러 가지 다른 매핑을
   사용할 수 있게 합니다. 기존 태그의 이름을 지정하면, 해당 태그가 열
   리고, 그렇지 않으면 이 이름의 새 태그가 만들어집니다. 이 매개 변수
   가 생략되거나 "None" 이면, 매핑은 이름 없이 만들어집니다. 태그 매개
   변수의 사용을 피하면 코드를 유닉스와 윈도우 사이에서 이식성 있게 유
   지할 수 있습니다.

   *offset*은 음이 아닌 정수 오프셋으로 지정할 수 있습니다. mmap 참조
   는 파일 시작 부분으로부터의 오프셋에 상대적입니다. *offset*의 기본
   값은 0입니다. *offset*은 "ALLOCATIONGRANULARITY"의 배수여야 합니다.

class mmap.mmap(fileno, length, flags=MAP_SHARED, prot=PROT_WRITE|PROT_READ, access=ACCESS_DEFAULT[, offset])

   **(유닉스 버전)** 파일 기술자 *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*를 모두 지정하는 것은 에러
   입니다. 이 매개 변수를 사용하는 방법에 대한 정보는 위의 *access* 설
   명을 참조하십시오.

   *offset*은 음이 아닌 정수 오프셋으로 지정할 수 있습니다. mmap 참조
   는 파일 시작 부분으로부터의 오프셋에 상대적입니다. *offset*의 기본
   값은 0입니다. *offset*은 유닉스 시스템에서 "PAGESIZE"와 같은
   "ALLOCATIONGRANULARITY"의 배수여야 합니다.

   생성된 메모리 매핑의 유효성을 보장하기 위해, 기술자 *fileno*로 지정
   된 파일은 맥 OS X 및 OpenVMS의 물리적 저장 장치와 내부적으로 자동
   동기화됩니다.

   이 예제는 "mmap"을 사용하는 간단한 방법을 보여줍니다:

      import mmap

      # write a simple example file
      with open("hello.txt", "wb") as f:
          f.write(b"Hello Python!\n")

      with open("hello.txt", "r+b") as f:
          # memory-map the file, size 0 means whole file
          mm = mmap.mmap(f.fileno(), 0)
          # read content via standard file methods
          print(mm.readline())  # prints b"Hello Python!\n"
          # read content via slice notation
          print(mm[:5])  # prints b"Hello"
          # update content using slice notation;
          # note that new content must have same size
          mm[6:] = b" world!\n"
          # ... and read again using standard file methods
          mm.seek(0)
          print(mm.readline())  # prints b"Hello  world!\n"
          # close the map
          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:  # In a child process
          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*가 지정되면, 지
      정된 바이트 범위의 변경 사항만 디스크로 플러시 됩니다; 그렇지 않
      으면, 매핑의 전체 범위가 플러시 됩니다. *offset*은 "PAGESIZE" 나
      "ALLOCATIONGRANULARITY"의 배수여야 합니다.

      **(윈도우 버전)** 반환된 0이 아닌 값은 성공을 나타냅니다; 0은 실
      패를 나타냅니다.

      **(유닉스 버전)** 성공을 나타내기 위해 0 값이 반환됩니다. 호출이
      실패하면 예외가 발생합니다.

   move(dest, src, count)

      오프셋 *src*에서 시작하는 *count* 바이트를 대상 인덱스 *dest*로
      복사합니다. mmap이 "ACCESS_READ"로 만들어졌으면, move를 호출하면
      "TypeError" 예외가 발생합니다.

   read([n])

      현재의 파일 위치로부터 최대 *n* 바이트를 포함하는 "bytes"를 반환
      합니다. 인자가 생략되거나 "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" (현재 위치를 기준으로 seek)과
      "os.SEEK_END" 또는 "2" (파일의 끝을 기준으로 seek)입니다.

   size()

      파일의 길이를 반환합니다. 메모리 매핑된 영역의 크기보다 클 수 있
      습니다.

   tell()

      파일 포인터의 현재 위치를 반환합니다.

   write(bytes)

      *bytes*의 바이트를 파일 포인터의 현재 위치에 있는 메모리에 기록
      하고 기록된 바이트 수를 반환합니다 (쓰기가 실패하면 "ValueError"
      가 발생하기 때문에 결코 "len(bytes)"보다 작지 않습니다). 파일 위
      치는 기록된 바이트 뒤를 가리 키도록 갱신됩니다. mmap이
      "ACCESS_READ"로 만들어졌으면, 기록할 때 "TypeError" 예외가 발생
      합니다.

      버전 3.5에서 변경: 이제 쓰기 가능한 *바이트열류 객체*를 받아들입
      니다.

      버전 3.6에서 변경: 이제 기록한 바이트 수가 반환됩니다.

   write_byte(byte)

      정수 *byte*를 파일 포인터의 현재 위치에 있는 메모리에 기록합니다
      ; 파일 위치가 "1" 증가합니다. mmap이 "ACCESS_READ"로 만들어졌으
      면, 기록할 때 "TypeError" 예외가 발생합니다.
