GeezerVison is showing docs.python.org — バッファプロトコル (buffer Protocol)
バッファプロトコル (buffer Protocol)¶
Pythonで利用可能ないくつかのオブジェクトは、下層にあるメモリ配列または buffer へのアクセスを提供します。このようなオブジェクトとして、組み込みの bytes や bytearray 、 array.array のようないくつかの拡張型が挙げられます。サードバーティのライブラリは画像処理や数値解析のような特別な目的のために、それら自身の型を定義することができます。
それぞれの型はそれ自身のセマンティクスを持ちますが、おそらく大きなメモリバッファからなるという共通の特徴を共有します。いくつかの状況では仲介するコピーを行うことなく直接バッファにアクセスすることが望まれます。
Python は バッファプロトコル によって、C レベルと Python レベルでこの機能を提供します。
このプロトコルには二つの側面があります。
bytes や bytearray などのシンプルなオブジェクトは、内部のバッファーをバイト列の形式で公開します。
バイト列以外の形式も利用可能です。例えば、 array.array が公開する要素はマルチバイト値になることがあります。
bufferインターフェースの利用者の一例は、ファイルオブジェクトの write() メソッドです: bufferインターフェースを通して一連のバイト列を提供できるどんなオブジェクトでもファイルに書き込むことができます。 write() は、その引数として渡されたオブジェクトの内部要素に対する読み出し専用アクセスのみを必要としますが、 readinto() のような他のメソッドでは、その引数の内容に対する書き込みアクセスが必要です。bufferインターフェースにより、オブジェクトは読み書き両方、読み出し専用バッファへのアクセスを許可するかそれとも拒否するか選択することができます。
bufferインターフェースの利用者には、対象となるオブジェクトのバッファを得る二つの方法があります:
どちらのケースでも、bufferが必要なくなった時に PyBuffer_Release() を呼び出さなければなりません。これを怠ると、リソースリークのような様々な問題につながる恐れがあります。
buffer 構造体¶
バッファ構造体(または単純に "buffers")は別のオブジェクトのバイナリデータをPythonプログラマに提供するのに便利です。これはまた、ゼロコピースライシング機構としても使用できます。このメモリブロックを参照する機能を使うことで、どんなデータでもとても簡単にPythonプログラマに提供することができます。メモリは、C 拡張の大きな配列定数かもしれませんし、オペレーティングシステムライブラリに渡す前のメモリブロックかもしれませんし、構造化データをネイティブのインメモリ形式受け渡すのに使用されるかもしれません。
Pythonインタプリタによって提供される多くのデータ型とは異なり、バッファは PyObject ポインタではなく、シンプルなC 構造体です。そのため、作成とコピーが非常に簡単に行えます。バッファの一般的なラッパーが必要なときは、 memoryview オブジェクトが作成されます。
エクスポートされるオブジェクトを書く方法の短い説明には、 Buffer Object Structures を参照してください。バッファを取得するには、 PyObject_GetBuffer() を参照してください。
-
type Py_buffer¶
- 次に属します: Stable ABI (すべてのメンバーを含む) (バージョン 3.11 より).
-
void *buf¶
バッファフィールドが表している論理構造の先頭を指すポインタ。
バッファを提供するオブジェクトの下層物理メモリブロック中のどの位置にもなりえます。
例えば strides が負だと、この値はメモリブロックの末尾かもしれません。
連続 配列の場合この値はメモリブロックの先頭を指します。
-
PyObject *obj¶
バッファを提供するオブジェクトへの新しい参照です。
この参照は利用側が所有し、PyBuffer_Release() によって自動的に解放 (参照カウントを減少) され、NULL に設定されます。
このフィールドは、通常の C API 関数の戻り値に相当します。
PyMemoryView_FromBuffer() または PyBuffer_FillInfo() によってラップされた 一時的な バッファである特別なケースでは、このフィールドは NULL です。一般的に、エクスポートオブジェクトはこの方式を使用してはなりません。
-
Py_ssize_t len¶
product(shape) * itemsize。contiguous配列では、下層のメモリブロックの長さになります。非contiguous 配列では、contiguous表現にコピーされた場合に論理構造がもつ長さです。
((char *)buf)[0] から ((char *)buf)[len-1] の範囲へのアクセスは、連続性 (contiguity) を保証するリクエストによって取得されたバッファに対してのみ許されます。
多くの場合に、そのようなリクエストは PyBUF_SIMPLE または PyBUF_WRITABLE です。
-
int readonly¶
バッファが読み出し専用であるか示します。このフィールドは PyBUF_WRITABLE フラグで制御できます。
-
Py_ssize_t itemsize¶
要素一つ分のbyte単位のサイズ。
struct.calcsize() を非 NULL の format 値に対して呼び出した結果と同じです。
重要な例外: 利用側が PyBUF_FORMAT フラグなしでバッファを要求した場合、format は NULL に設定されますが、itemsize は元の形式に対応する値を保持します。
shape が存在する場合、 product(shape) * itemsize == len の等式が守られ、利用者は itemsize を buffer を読むために利用できます。
PyBUF_SIMPLE または PyBUF_WRITABLE で要求した結果、 shape が NULL であれば、消費者は itemsize を無視して itemsize == 1 と見なさなければなりません。
-
char *format¶
単一の要素の内容を struct モジュール形式の構文で記述した、ヌル終端文字列です。
NULL の場合は "B" (符号なしバイト) とみなします。
このフィールドは PyBUF_FORMAT フラグによって制御されます。
-
int ndim¶
メモリを n 次元配列として表すときの次元数です。
0 の場合、buf はスカラを表す単一の要素を指します。
この場合、shape、strides、suboffsets は NULL でなければなりません。
次元数の上限は PyBUF_MAX_NDIM で定義されています。
-
Py_ssize_t *shape¶
メモリ上のN次元配列の形を示す、長さが ndim である Py_ssize_t の配列です。
shape[0] * ... * shape[ndim-1] * itemsize は len と等しくなければなりません。
shape の値は shape[n] >= 0 に制限されます。 shape[n] == 0 の場合に特に注意が必要です。
詳細は complex arrays を参照してください。
shape 配列は利用側にとって読み取り専用です。
-
Py_ssize_t *strides¶
各次元において新しい値を得るためにスキップするバイト数を示す、長さ ndim の Py_ssize_t の配列。
ストライドの値は任意の整数です。
通常の配列ではストライドは一般に正ですが、利用側は strides[n] <= 0 の場合も扱えなければなりません。
詳細は complex arrays を参照してください。
消費者にとって、この strides 配列は読み出し専用です。
-
Py_ssize_t *suboffsets¶
Py_ssize_t 型の要素を持つ長さ ndim の配列。
suboffsets[n] >= 0 の場合は、 n 番目の次元に沿って保存されている値はポインタで、 suboffset 値は各ポインタの参照を解決した後に何バイト加えればいいかを示しています。
suboffset の値が負の数の場合は、ポインタの参照解決は不要 (連続したメモリブロック内に直接配置されいる) ということになります。
全ての suboffset が負数の場合 (つまり参照解決が不要) な場合、このフィールドは NULL (デフォルト値) でなければなりません。
この種の配列表現は Python Imaging Library (PIL) で使われています。
このような配列で要素にアクセスする方法についてさらに詳しことは complex arrays を参照してください。
消費者にとって、suboffsets 配列は読み出し専用です。
-
void *internal¶
バッファを提供する側のオブジェクトが内部的に利用するための変数です。例えば、提供側はこの変数に整数型をキャストして、shape, strides, suboffsets といった配列をバッファを開放するときに同時に解放するべきかどうかを管理するフラグに使うことができるでしょう。バッファを受け取る側は、この値を決して変更してはなりません。
定数。
-
PyBUF_MAX_NDIM¶
- 次に属します: Stable ABI (バージョン 3.11 より).
メモリを表す次元数の上限です。
バッファの提供側はこの上限を守らなければなりません。
多次元バッファの利用側は PyBUF_MAX_NDIM 次元まで扱えるべきです。
現在は 64 に設定されています。
バッファリクエストのタイプ¶
バッファは通常、 PyObject_GetBuffer() を使うことで、エクスポートするオブジェクトにバッファリクエストを送ることで得られます。メモリの論理的な構造の複雑性は多岐にわたるため、消費者は flags 引数を使って、自身が扱えるバッファの種類を指定します。
Py_buffer の全フィールドは、リクエストの種類によって曖昧さを残さずに定義されます。
readonly, format¶
-
PyBUF_WRITABLE¶
- 次に属します: Stable ABI (バージョン 3.11 より).
readonly フィールドを制御します。
設定されている場合、提供側は書き込み可能なバッファを提供するか、失敗を報告しなければなりません。
設定されていない場合は、読み取り専用でも書き込み可能でも構いませんが、すべての利用側に対して一貫した選択をする必要があります。
例えば PyBUF_SIMPLE | PyBUF_WRITABLE で、単純な書き込み可能バッファを要求できます。
-
PyBUF_WRITEABLE¶
PyBUF_WRITABLE の別名です。
-
PyBUF_FORMAT¶
- 次に属します: Stable ABI (バージョン 3.11 より).
format フィールドを制御します。もしフラグが設定されていれば、このフィールドを正しく埋めなければなりません。フラグが設定されていなければ、このフィールドを NULL に設定しなければなりません。
PyBUF_WRITABLE は、次の節に出てくるどのフラグとも | を取ってかまいません。
PyBUF_SIMPLE は 0 と定義されているので、 PyBUF_WRITABLE は単純な書き込み可能なバッファを要求する単独のフラグとして使えます。
PyBUF_FORMAT は、PyBUF_SIMPLE 以外のいずれかのフラグとビット OR で組み合わせる必要があります。
PyBUF_SIMPLE はすでに形式 B (符号なしバイト) を意味するためです。
PyBUF_FORMAT を単独で使うことはできません。
shape, strides, suboffsets¶
このフラグは、以下で複雑性が大きい順に並べたメモリの論理的な構造を制御します。個々のフラグは、それより下に記載されたフラグのすべてのビットを含むことに注意してください。
これらの値は、バージョン 3.11 以降の Stable ABI を対象としてコンパイルする場合に利用できます。
リクエスト |
shape |
strides |
suboffsets |
-
PyBUF_INDIRECT¶
|
yes |
yes |
必要な場合 |
-
PyBUF_STRIDES¶
|
yes |
yes |
NULL |
-
PyBUF_ND¶
|
yes |
NULL |
NULL |
-
PyBUF_SIMPLE¶
|
NULL |
NULL |
NULL |
隣接性のリクエスト¶
C スタイルまたは Fortran スタイルの 連続性 は、ストライド情報の有無にかかわらず明示的に要求できます。
ストライド情報がない場合、バッファは C スタイルで連続していなければなりません。
これらの値は、バージョン 3.11 以降の Stable ABI を対象としてコンパイルする場合に利用できます。
リクエスト |
shape |
strides |
suboffsets |
contig |
-
PyBUF_C_CONTIGUOUS¶
|
yes |
yes |
NULL |
C |
-
PyBUF_F_CONTIGUOUS¶
|
yes |
yes |
NULL |
F |
-
PyBUF_ANY_CONTIGUOUS¶
|
yes |
yes |
NULL |
C か F |
PyBUF_ND
|
yes |
NULL |
NULL |
C |
複合リクエスト¶
有り得る全てのリクエストの値は、前の節でのフラグの組み合わせで網羅的に定義されています。
便利なように、バッファープロトコルでは頻繁に使用される組み合わせを単一のフラグとして提供してます。
次のテーブルの U は連続性が未定義であることを表します。
利用者は PyBuffer_IsContiguous() を呼び出して連続性を判定する必要があるでしょう。
これらの値は、バージョン 3.11 以降の Stable ABI を対象としてコンパイルする場合に利用できます。
リクエスト |
shape |
strides |
suboffsets |
contig |
readonly |
format |
-
PyBUF_FULL¶
|
yes |
yes |
必要な場合 |
U |
0 |
yes |
-
PyBUF_FULL_RO¶
|
yes |
yes |
必要な場合 |
U |
1 か 0 |
yes |
-
PyBUF_RECORDS¶
|
yes |
yes |
NULL |
U |
0 |
yes |
-
PyBUF_RECORDS_RO¶
|
yes |
yes |
NULL |
U |
1 か 0 |
yes |
-
PyBUF_STRIDED¶
|
yes |
yes |
NULL |
U |
0 |
NULL |
-
PyBUF_STRIDED_RO¶
|
yes |
yes |
NULL |
U |
1 か 0 |
NULL |
-
PyBUF_CONTIG¶
|
yes |
NULL |
NULL |
C |
0 |
NULL |
-
PyBUF_CONTIG_RO¶
|
yes |
NULL |
NULL |
C |
1 か 0 |
NULL |
複雑な配列¶
NumPy スタイル: shape, strides¶
NumPy スタイルの配列の論理的構造は itemsize, ndim, shape, strides で定義されます。
ndim == 0 の場合は、 buf が指すメモリの場所は、サイズが itemsize のスカラ値として解釈されます。
この場合、 shape と strides の両方とも NULL です。
strides が NULL の場合は、配列は標準の n 次元 C 配列として解釈されます。
そうでない場合は、利用者は次のように n 次元配列にアクセスしなければなりません:
ptr = (char *)buf + indices[0] * strides[0] + ... + indices[n-1] * strides[n-1];
item = *((typeof(item) *)ptr);
上記のように、 buf はメモリブロック内のどの場所でも指すことが可能です。エクスポーターはこの関数を使用することによってバッファの妥当性を確認出来ます。
def verify_structure(memlen, itemsize, ndim, shape, strides, offset):
"""引数が、割り当てたメモリの範囲内の有効な配列を
表しているかどうかを検証する:
char *mem: 物理メモリブロックの先頭
memlen: 物理メモリブロックの長さ
offset: (char *)buf - mem
"""
if offset % itemsize:
return False
if offset < 0 or offset+itemsize > memlen:
return False
if any(v % itemsize for v in strides):
return False
if ndim <= 0:
return ndim == 0 and not shape and not strides
if 0 in shape:
return True
imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)
if strides[j] <= 0)
imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)
if strides[j] > 0)
return 0 <= offset+imin and offset+imax+itemsize <= memlen
PIL スタイル: shape, strides, suboffsets¶
PIL スタイルの配列では通常の要素の他に、ある次元の上で次の要素を取得するために辿るポインタを持てます。
例えば、通常の3次元 C 配列 char v[2][2][3] は、2次元配列への 2 つのポインタからなる配列 char (*v[2])[2][3] と見ることもできます。
suboffset 表現では、これらの 2 つのポインタは buf の先頭に埋め込め、メモリのどこにでも配置できる 2 つの char x[2][3] 配列を指します。
次の例は、 strides も suboffsets も NULL でない場合の、N 次元インデックスによって指されている N 次元配列内の要素へのポインタを返す関数です:
void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,
Py_ssize_t *suboffsets, Py_ssize_t *indices) {
char *pointer = (char*)buf;
int i;
for (i = 0; i < ndim; i++) {
pointer += strides[i] * indices[i];
if (suboffsets[i] >=0 ) {
pointer = *((char**)pointer) + suboffsets[i];
}
}
return (void*)pointer;
}
バッファ関連の関数¶
-
int PyObject_CheckBuffer(PyObject *obj)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
obj がbuffer インターフェースをサポートしている場合は 1 を返し、そうでない場合は 0 を返します。
1 を返したとしても、 PyObject_GetBuffer() が成功することは保証されません。
この関数は常に成功します。
-
int PyObject_GetBuffer(PyObject *exporter, Py_buffer *view, int flags)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
exporter に flags で指定された方法で view を埋めるように要求します。もし exporter が指定されたとおりにバッファを提供できない場合、 BufferError を送出し、 view->obj を NULL に設定した上で、 -1 を返さなければなりません。
成功した場合は view に情報を設定し、view->obj を exporter への新しい参照にして 0 を返します。
複数のバッファ提供側が連鎖し、要求を一つのオブジェクトに転送する場合は、view->obj が exporter の代わりにそのオブジェクトを参照しても構いません (バッファオブジェクト構造体 を参照)。
malloc() と free() のように、呼び出しに成功した PyObject_GetBuffer() と対になる PyBuffer_Release() の呼び出しがなけれなればなりません。
従って、バッファの利用が済んだら PyBuffer_Release() が厳密に1回だけ呼び出されなければなりません。
-
void PyBuffer_Release(Py_buffer *view)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
バッファ view を解放し、ビューを支えるオブジェクト view->obj への 強参照 も解放します (つまり参照カウントを減らします)。
バッファを使わなくなったときは必ず呼び出してください。
呼び出さないと参照がリークする可能性があります。
PyObject_GetBuffer() を通して取得していないバッファに対してこの関数を呼び出すのは間違いです。
-
Py_ssize_t PyBuffer_SizeFromFormat(const char *format)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
format が表す itemsize を返します。
エラーの場合は例外を送出し、-1 を返します。
-
int PyBuffer_IsContiguous(const Py_buffer *view, char order)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
view で定義されているメモリが、 C スタイル (order == 'C') のときか、 Fortran スタイル (order == 'F') 連続 のときか、そのいずれか (order == 'A') であれば 1 を返します。
それ以外の場合は 0 を返します。
この関数は常に成功します。
-
void *PyBuffer_GetPointer(const Py_buffer *view, const Py_ssize_t *indices)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
与えられた view 内にある indices が指すメモリ領域を取得します。
indices は view->ndim 個のインデックスからなる配列を指していなければなりません。
-
int PyBuffer_FromContiguous(const Py_buffer *view, const void *buf, Py_ssize_t len, char order)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
buf の連続した len バイトを view にコピーします。
order は 'C'、'F'、'A' のいずれかで、それぞれ C スタイル、Fortran スタイル、どちらでもよいことを表します。
成功した場合は 0 を返し、エラーの場合は -1 を返します。
-
int PyBuffer_ToContiguous(void *buf, const Py_buffer *src, Py_ssize_t len, char order)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
src の len バイトを、buf 内の連続した表現にコピーします。
order は 'C'、'F'、'A' のいずれかで、それぞれ C スタイル、Fortran スタイル、どちらでもよいことを表します。
成功した場合は 0 を返し、エラーの場合は -1 を返します。
len != src->len の場合、この関数は失敗します。
-
int PyObject_CopyData(PyObject *dest, PyObject *src)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
src から dest バッファにデータをコピーします。
C スタイルと Fortran スタイルのバッファ間で変換できます。
成功したら 0 が、エラー時には -1 が返されます。
-
void PyBuffer_FillContiguousStrides(int ndims, Py_ssize_t *shape, Py_ssize_t *strides, int itemsize, char order)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
指定された形状と要素あたりのバイト数を持つ 連続した 配列の、バイト単位のストライドを strides 配列に設定します。
order が 'C' なら C スタイル、'F' なら Fortran スタイルです。
-
int PyBuffer_FillInfo(Py_buffer *view, PyObject *exporter, void *buf, Py_ssize_t len, int readonly, int flags)¶
- 次に属します: Stable ABI (バージョン 3.11 より).
サイズが len の buf を readonly に従った書き込み可/不可の設定で公開するバッファリクエストを処理します。
buf は符号無しバイトの列として解釈されます。
flags 引数は要求の種類を示します。
buf が読み取り専用なのに flags に PyBUF_WRITABLE が設定されている場合を除き、この関数は常に flags の指定どおりに view に情報を設定します。
成功した場合は view->obj を exporter への新しい参照に設定し、0 を返します。
それ以外の場合は BufferError を送出し、view->obj を NULL に設定して -1 を返します。
この関数を getbufferproc の一部として使う場合には、 exporter はエクスポートするオブジェクトに設定しなければならず、さらに flags は変更せずに渡さなければなりません。
そうでない場合は、 exporter は NULL でなければなりません。
© Copyright 2001 Python Software Foundation.
このページはPython Software Foundation License Version 2でライセンスされています。
ドキュメント内のサンプル、レシピ等のコードは、Zero Clause BSDライセンスの下で追加的にライセンスされています。
詳しくは 歴史とライセンスを参照してください。
Pythonソフトウェア財団は非営利法人です。
寄付をするには
最終更新日: 11月 12, 2026 (08:26 UTC)
バグを報告する
Sphinx9.1.1を使って構築されています。
|