16.7. "mmap" --- メモリマップファイル
*************************************

メモリにマップされたファイルオブジェクトは、文字列とファイルオブジェク
トの両方のように振舞います。しかし通常の文字列オブジェクトとは異なり、
これらは可変です。文字列が期待されるほとんどの場所で mmap オブジェクト
を利用できます。例えば、メモリマップファイルを探索するために "re" モジ
ュールを使うことができます。それらは可変なので、 "obj[index] = 'a'" の
ように文字を変換できますし、スライスを使うことで "obj[i1:i2] = '...'"
のように部分文字列を変換することができます。現在のファイル位置をデータ
の始めとする読込みや書込み、ファイルの異なる位置へ "seek()" することも
できます。

メモリマップドファイルは Unix と Windows で異なる "mmap" コンストラク
タで生成されます。どちらの場合も、更新用に開かれたファイルディスクリプ
タを渡さなければなりません。既存の Python ファイルオブジェクトをマップ
したければ、 "fileno()" メソッドを使って *fileno* パラメータの正しい値
を取得してください。そうでなければ、 "os.open()" 関数を使ってファイル
を開けます。この関数はファイルディスクリプタを直接返します(処理が終わ
ったら、やはりファイルを閉じる必要があります)。

注釈: 書き込み可能でバッファされたファイルへのメモリマップファイルを
  作りた いのであれば、まず最初にファイルの "flush()" を呼び出すべきで
  す。こ れはバッファへのローカルな修正がマッピングで実際に利用可能に
  なること を保障するために必要です。

Unix バージョンと Windows バージョンのどちらのコンストラクタについても
、オプションのキーワード・パラメータとして *access* を指定することにな
るかもしれません。 *access* は3つの値の内の1つを受け入れます。
"ACCESS_READ" は読み込み専用、 "ACCESS_WRITE" は書き込み可能、
"ACCESS_COPY" はコピーした上での書き込みです。 *access* は Unix と
Windows の両方で使用することができます。 *access* が指定されない場合、
Windows の mmap は書き込み可能マップを返します。 3つのアクセス型すべて
に対する初期メモリ値は、指定されたファイルから得られます。
"ACCESS_READ" 型のメモリマップに対して書き込むと "TypeError" 例外を送
出します。 "ACCESS_WRITE" 型のメモリマップへの書き込みはメモリと元のフ
ァイルの両方に影響を与えます。 "ACCESS_COPY" 型のメモリマップへの書き
込みはメモリに影響を与えますが、元のファイルを更新することはありません
。

バージョン 2.5 で変更: 無名メモリ(anonymous memory)にマップするために
は fileno として -1 を渡し、length を与えてください。

バージョン 2.6 で変更: mmap.mmap はこれまで mmap オブジェクトを生成す
るファクトリ関数でした。これからは mmap.mmap がクラスそのものになりま
す。

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

   **(Windows バージョン)** ファイルハンドル *fileno* によって指定され
   たファイルから *length* バイトをマップして、 mmap オブジェクトを生
   成します。 *length* が現在のファイルサイズより大きな場合、ファイル
   サイズは *length* を含む大きさにまで拡張されます。 *length* が "0"
   の場合、マップの最大の長さは現在のファイルサイズになります。ただし
   、ファイル自体が空のときは Windows が例外を送出します (Windows では
   空のマップを作成することができません)。

   *tagname* は、 "None" 以外で指定された場合、マップのタグ名を与える
   文字列となります。 Windows は同じファイルに対する様々なマップを持つ
   ことを可能にします。既存のタグの名前を指定すればそのタグがオープン
   され、そうでなければこの名前の新しいタグが作成されます。もしこのパ
   ラメータを省略したり "None" を与えたりしたならば、マップは名前なし
   で作成されます。タグ・パラメータの使用の回避は、あなたのコードを
   Unix と Windows の間で移植可能にしておくのを助けてくれるでしょう。

   *offset* may be specified as a non-negative integer offset. mmap
   references will be relative to the offset from the beginning of the
   file. *offset* defaults to 0.  *offset* must be a multiple of the
   "ALLOCATIONGRANULARITY".

class mmap.mmap(fileno, length[, flags[, prot[, access[, offset]]]])

   **(Unix バージョン)** ファイルディスクリプタ *fileno* で指定された
   ファイルから *length* バイトをマップし、mmap オブジェクトを返します
   。*length* が "0" の場合、マップの最大の長さは "mmap" が呼ばれた時
   点でのファイルサイズになります。

   *flags* はマップの種類を指定します。 "MAP_PRIVATE" はプライベートな
   copy-on-write(書込み時コピー)のマップを作成します。従って、mmap オ
   ブジェクトの内容への変更はこのプロセス内にのみ有効です。
   "MAP_SHARED" はファイルの同じ領域をマップする他のすべてのプロセスと
   共有されたマップを作成します。デフォルトは "MAP_SHARED" です。

   *prot* が指定された場合、希望のメモリ保護を与えます。 2つの最も有用
   な値は、 "PROT_READ" と "PROT_WRITE" です。これは、読込み可能または
   書込み可能を指定するものです。 *prot* のデフォルトは "PROT_READ |
   PROT_WRITE" です。

   *access* はオプションのキーワード・パラメータとして、 *flags* と
   *prot* の代わりに指定してもかまいません。 *flags*, *prot* と
   *access* の両方を指定することは間違っています。このパラメーターを使
   用法についての情報は、先に述べた *access* の記述を参照してください
   。

   *offset* may be specified as a non-negative integer offset. mmap
   references will be relative to the offset from the beginning of the
   file. *offset* defaults to 0. *offset* must be a multiple of
   "ALLOCATIONGRANULARITY" which is equal to "PAGESIZE" on Unix
   systems.

   Mac OS X と OpenVMS において、作成された memory mapping の正当性を
   確実にするために *fileno* で指定されたファイルディスクリプタは内部
   で自動的に物理的なストレージ (physical backing store) と同期されま
   す。

   この例は "mmap" の簡潔な使い方を示すものです:

      import mmap

      # write a simple example file
      with open("hello.txt", "wb") as f:
          f.write("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 "Hello Python!"
          # read content via slice notation
          print mm[:5]  # prints "Hello"
          # update content using slice notation;
          # note that new content must have same size
          mm[6:] = " world!\n"
          # ... and read again using standard file methods
          mm.seek(0)
          print mm.readline()  # prints "Hello  world!"
          # close the map
          mm.close()

   次の例では無名マップを作り親プロセスと子プロセスの間でデータのやり
   とりをしてみせます:

      import mmap
      import os

      mm = mmap.mmap(-1, 13)
      mm.write("Hello world!")

      pid = os.fork()

      if pid == 0:  # In a child process
          mm.seek(0)
          print mm.readline()

          mm.close()

   メモリマップファイルオブジェクトは以下のメソッドをサポートしていま
   す:

   close()

      メモリマップファイルを閉じます。この呼出しの後にオブジェクトの他
      のメソッドの呼出すことは、 "ValueError" 例外の送出を引き起こしま
      す。このメソッドは開いたファイルのクローズはしません。

   find(string[, start[, end]])

      オブジェクト内の [*start*, *end*] の範囲に含まれている部分文字列
      *string* が見つかった場所の最も小さいインデックスを返します。オ
      プションの引数 *start* と *end* はスライスに使われるときのように
      解釈されます。失敗したときには "-1" を返します。

   flush([offset, size])

      Flushes changes made to the in-memory copy of a file back to
      disk. Without use of this call there is no guarantee that
      changes are written back before the object is destroyed.  If
      *offset* and *size* are specified, only changes to the given
      range of bytes will be flushed to disk; otherwise, the whole
      extent of the mapping is flushed.  *offset* must be a multiple
      of the "PAGESIZE" or "ALLOCATIONGRANULARITY".

      **(Windows バージョン)** ゼロ以外の値が返されたら成功を、ゼロは
      失敗を意味します。

      **(Unix バージョン)** ゼロの値が返されたら成功を意味します。呼び
      出しが失敗すると例外が送出されます。

   move(dest, src, count)

      オフセット *src* から始まる *count* バイトをインデックス *dest*
      の位置へコピーします。もし mmap が "ACCESS_READ" で作成されてい
      た場合、 "TypeError" 例外を発生させます。

   read(num)

      現在のファイル位置から最大で *num* バイト分の文字列を返します。
      ファイル位置は返したバイトの分だけ後ろの位置へ更新されます。

   read_byte()

      現在のファイル位置から長さ1の文字列を返します。ファイル位置は1だ
      け進みます。

   readline()

      現在のファイル位置から次の改行までの、1行を返します。

   resize(newsize)

      マップと元ファイル(がもしあれば)のサイズを変更します。もし mmap
      が "ACCESS_READ" または "ACCESS_COPY" で作成されたならば、マップ
      サイズの変更は "TypeError" 例外を発生させます。

   rfind(string[, start[, end]])

      オブジェクト内の [*start*, *end*] の範囲に含まれている部分文字列
      *string* が見つかった場所の最も大きいインデックスを返します。オ
      プションの引数 *start* と *end* はスライスに使われるときのように
      解釈されます。失敗したときには "-1" を返します。

   seek(pos[, whence])

      ファイルの現在位置をセットします。 *whence* 引数はオプションであ
      り、デフォルトは "os.SEEK_SET" つまり "0" (絶対位置)です。その他
      の値として、 "os.SEEK_CUR" つまり "1" (現在位置からの相対位置)と
      "os.SEEK_END" つまり "2" (ファイルの終わりからの相対位置)があり
      ます。

   size()

      ファイルの長さを返します。メモリマップ領域のサイズより大きいかも
      しれません。

   tell()

      ファイルポインタの現在位置を返します。

   write(string)

      メモリ内のファイルポインタの現在位置に *string* のバイト列を書き
      込みます。ファイル位置はバイト列が書き込まれた後の位置へ更新され
      ます。もし mmap が "ACCESS_READ" で作成されていた場合、書き込み
      時に "TypeError" 例外を発生させるでしょう。

   write_byte(byte)

      メモリ内のファイルポインタの現在位置に単一文字の文字列 *byte* を
      書き込みます。ファイル位置は "1" だけ進みます。もし mmap が
      "ACCESS_READ" で作成されていた場合、書き込み時に "TypeError" 例
      外を発生させるでしょう。
