バッファとMemoryviewオブジェクト—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/c-api/buffer
移動先:案内検索

バッファとMemoryviewオブジェクト

Cで実装されたPythonオブジェクトは、「バッファインターフェイス」と呼ばれる関数のグループをエクスポートできます。 これらの関数は、オブジェクトがそのデータを生のバイト指向形式で公開するために使用できます。 オブジェクトのクライアントは、バッファインターフェイスを使用して、最初にオブジェクトデータをコピーしなくても、オブジェクトデータに直接アクセスできます。

バッファインターフェイスをサポートするオブジェクトの2つの例は、文字列と配列です。 文字列オブジェクトは、バッファインターフェイスのバイト指向の形式で文字の内容を公開します。 配列は、古いスタイルのバッファインターフェイスを介してのみその内容を公開できます。 この制限は、 memoryview オブジェクトを配列から構築できるPython3には適用されません。 配列要素はマルチバイト値の場合があります。

バッファインターフェイスのユーザーの例は、ファイルオブジェクトのwrite()メソッドです。 バッファインターフェイスを介して一連のバイトをエクスポートできるオブジェクトはすべて、ファイルに書き込むことができます。 PyArg_ParseTuple()には、オブジェクトのバッファインターフェイスに対して動作し、ターゲットオブジェクトからデータを返すフォーマットコードがいくつかあります。

バージョン1.6以降、PythonはPythonレベルのバッファーオブジェクトとCレベルのバッファーAPIを提供しており、組み込み型または使用済み定義型がその特性を公開できるようになっています。 ただし、どちらもさまざまな欠点のために非推奨になり、Python 3で正式に削除され、新しいCレベルのバッファAPIと memoryview という名前の新しいPythonレベルのオブジェクトが採用されました。

新しいバッファAPIはPython2.6にバックポートされ、 memoryview オブジェクトはPython2.7にバックポートされました。 互換性の理由で使用がブロックされていない限り、古いAPIではなくそれらを使用することを強くお勧めします。

新しいスタイルのPy_buffer構造体

type Py_buffer
void *buf

オブジェクトのメモリの開始へのポインタ。

int readonly

バッファが読み取り専用かどうかのインジケータ。

int ndim

メモリが多次元配列として表す次元の数。 0の場合、 strides および suboffsetsNULL である必要があります。

Py_ssize_t *shape

Py_ssize_tの長さが ndim の配列であり、多次元配列としてメモリの形状を示します。 ((*shape)[0] * ... * (*shape)[ndims-1])*itemsizelenと等しくなければならないことに注意してください。

Py_ssize_t *strides

Py_ssize_tの配列は ndim の長さであり、各次元の新しい要素に到達するためにスキップするバイト数を示します。

Py_ssize_t *suboffsets

Py_ssize_tの配列は ndim の長さです。 これらのサブオフセット番号が0以上の場合、示された次元に沿って格納された値はポインターであり、サブオフセット値は、参照解除後にポインターに追加するバイト数を決定します。 負のサブオフセット値は、逆参照が発生してはならないことを示します(連続したメモリブロックをストライドします)。

すべてのサブオフセットが負の場合(つまり、 参照解除は必要ありません)、このフィールドはNULL(デフォルト値)である必要があります。

NULL以外のストライドとサブオフセットの両方がある場合に、N次元インデックスが指すND配列内の要素へのポインターを返す関数を次に示します。

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;
 }
Py_ssize_t itemsize

これは、共有メモリの各要素のアイテムサイズ(バイト単位)のストレージです。 PyBuffer_SizeFromFormat()を使用して取得できるため、技術的には不要ですが、エクスポーターはフォーマット文字列を解析せずにこの情報を知っている可能性があり、ストライドを適切に解釈するにはアイテムサイズを知る必要があります。 したがって、それを保存することはより便利でより速くなります。

void *internal

これは、エクスポートするオブジェクトが内部で使用するためのものです。 たとえば、これはエクスポータによって整数として再キャストされ、バッファが解放されたときにシェイプ、ストライド、およびサブオフセット配列を解放する必要があるかどうかに関するフラグを格納するために使用される場合があります。 消費者はこの値を決して変更してはなりません。


MemoryViewオブジェクト

バージョン2.7の新機能。


memoryview オブジェクトは、新しいCレベルのバッファインターフェイスをPythonオブジェクトとして公開し、他のオブジェクトと同じように渡すことができます。

PyObject *PyMemoryView_FromObject(PyObject *obj)
新しいバッファインターフェイスを定義するオブジェクトからmemoryviewオブジェクトを作成します。
PyObject *PyMemoryView_FromBuffer(Py_buffer *view)
指定されたbuffer-info構造 view をラップするmemoryviewオブジェクトを作成します。 次に、memoryviewオブジェクトがバッファを所有します。つまり、自分でバッファを解放しようとしないでください。memoryviewオブジェクトの割り当て解除時に解放されます。
PyObject *PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
バッファインターフェイスを定義するオブジェクトから、メモリの連続したチャンク( 'C'または 'F'ortran order )にmemoryviewオブジェクトを作成します。 メモリが連続している場合、memoryviewオブジェクトは元のメモリを指します。 それ以外の場合はコピーが作成され、memoryviewは新しいbytesオブジェクトを指します。
int PyMemoryView_Check(PyObject *obj)
オブジェクト obj がmemoryviewオブジェクトの場合はtrueを返します。 現在、 memoryview のサブクラスを作成することは許可されていません。
Py_buffer *PyMemoryView_GET_BUFFER(PyObject *obj)
指定されたオブジェクトによってラップされたbuffer-info構造へのポインタを返します。 オブジェクトはmemoryviewインスタンスである必要があります。 このマクロはそのタイプをチェックしません。自分でチェックする必要があります。そうしないと、クラッシュする危険があります。


古いスタイルのバッファオブジェクト

古いバッファインターフェイスの詳細については、バッファオブジェクト構造のセクションの PyBufferProcs の説明を参照してください。

「バッファオブジェクト」は、bufferobject.hヘッダー(Python.hに含まれています)で定義されています。 これらのオブジェクトは、Pythonプログラミングレベルの文字列オブジェクトと非常によく似ています。スライス、インデックス作成、連結、およびその他の標準的な文字列操作をサポートしています。 ただし、それらのデータは、メモリのブロックから、またはバッファインターフェイスをエクスポートする別のオブジェクトからの2つのソースのいずれかから取得できます。

バッファオブジェクトは、別のオブジェクトのバッファインターフェイスからPythonプログラマにデータを公開する方法として役立ちます。 また、ゼロコピーのスライスメカニズムとしても使用できます。 メモリのブロックを参照する機能を使用すると、Pythonプログラマーに任意のデータを非常に簡単に公開できます。 メモリは、C拡張機能の大きな定数配列、オペレーティングシステムライブラリに渡す前の操作用の生のメモリブロック、またはネイティブのメモリ内形式で構造化データを渡すために使用できます。 。

type PyBufferObject
PyObject のこのサブタイプは、バッファーオブジェクトを表します。
PyTypeObject PyBuffer_Type
Pythonバッファタイプを表す PyTypeObject のインスタンス。 Pythonレイヤーのbufferおよびtypes.BufferTypeと同じオブジェクトです。 .
int Py_END_OF_BUFFER
この定数は、 size パラメーターとして PyBuffer_FromObject()または PyBuffer_FromReadWriteObject()に渡すことができます。 これは、新しい PyBufferObject が、指定された offset からエクスポートされたバッファーの終わりまでの base オブジェクトを参照する必要があることを示しています。 これを使用すると、呼び出し元は base オブジェクトにその長さを照会することを回避できます。
int PyBuffer_Check(PyObject *p)
引数の型が PyBuffer_Type の場合、trueを返します。
PyObject *PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)

新しい読み取り専用バッファオブジェクトを返します。 これにより、 base が読み取り専用バッファプロトコルをサポートしていないか、バッファセグメントを1つだけ提供していない場合、TypeErrorが発生します。または、 offsetの場合、ValueErrorが発生します。 がゼロ未満です。 バッファは base オブジェクトへの参照を保持し、バッファの内容は base オブジェクトのバッファインターフェイスを参照し、位置 offset から始まり、[ X202X] size バイト。 sizePy_END_OF_BUFFERの場合、新しいバッファーの内容は、 base オブジェクトのエクスポートされたバッファーデータの長さまで拡張されます。

バージョン2.5で変更:この関数は、オフセットおよびサイズintタイプを使用していました。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。

PyObject *PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)

新しい書き込み可能なバッファオブジェクトを返します。 パラメータと例外は、 PyBuffer_FromObject()の場合と同様です。 base オブジェクトが書き込み可能なバッファプロトコルをエクスポートしない場合、TypeErrorが発生します。

バージョン2.5で変更:この関数は、オフセットおよびサイズintタイプを使用していました。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。

PyObject *PyBuffer_FromMemory(void *ptr, Py_ssize_t size)

指定されたサイズで、メモリ内の指定された場所から読み取る新しい読み取り専用バッファオブジェクトを返します。 呼び出し元は、 ptr として渡されたメモリバッファが、返されたバッファオブジェクトが存在する間、割り当てが解除されないようにする責任があります。 size がゼロ未満の場合、ValueErrorを上げます。 Py_END_OF_BUFFERsize パラメーターに渡されない場合があることに注意してください。 その場合、ValueErrorが発生します。

バージョン2.5で変更:この関数は、サイズintタイプを使用していました。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。

PyObject *PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)

PyBuffer_FromMemory()に似ていますが、返されたバッファーは書き込み可能です。

バージョン2.5で変更:この関数は、サイズintタイプを使用していました。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。

PyObject *PyBuffer_New(Py_ssize_t size)

size バイトの独自のメモリバッファを維持する新しい書き込み可能なバッファオブジェクトを返します。 ValueErrorは、 size がゼロまたは正でない場合に返されます。 メモリバッファ( PyObject_AsWriteBuffer()によって返される)は特に整列されていないことに注意してください。

バージョン2.5で変更:この関数は、サイズintタイプを使用していました。 これには、64ビットシステムを適切にサポートするためにコードの変更が必要になる場合があります。