buffer.md
1> **Источник:** https://python-all.ru/2.6/c-api/buffer.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Буферные объекты89Объекты Python, реализованные на C, могут экспортировать группу функций, называемую «буферным интерфейсом». Эти функции могут использоваться объектом для предоставления своих данных в сыром, байт-ориентированном формате. Клиенты объекта могут использовать буферный интерфейс для прямого доступа к данным объекта без необходимости их предварительного копирования.1011Два примера объектов, поддерживающих буферный интерфейс: строки и массивы. Строка предоставляет содержимое символов в байт-ориентированной форме буферного интерфейса. Массив также может предоставлять свое содержимое, но следует помнить, что элементы массива могут быть многобайтовыми.1213Примером потребителя буферного интерфейса является метод `write()` файлового объекта. Любой объект, способный экспортировать последовательность байтов через буферный интерфейс, может быть записан в файл. Существует ряд кодов формата для [`PyArg_ParseTuple()`](https://python-all.ru/2.6/c-api/arg.html#PyArg_ParseTuple), которые работают с буферным интерфейсом объекта, возвращая данные из целевого объекта.1415Начиная с версии 1.6, Python предоставлял буферные объекты на уровне Python и C-API буфера, чтобы любой встроенный или пользовательский тип мог предоставлять свои характеристики. Однако оба они были объявлены устаревшими из-за различных недостатков и официально удалены в Python 3.0 в пользу нового C-API буфера и нового объекта на уровне Python с именем `memoryview`.1617Новый буферный API был перенесен в Python 2.6, а объект `memoryview` – в Python 2.7. Настоятельно рекомендуется использовать их вместо старых API, если только совместимость не вынуждает использовать старые.1819## Структура Py\_buffer нового стиля2021**`Py_buffer`**2223**void \*`buf`**2425Указатель на начало памяти объекта.2627**Py\_ssize\_t `len`**2829Общая длина памяти в байтах.3031**int `readonly`**3233Индикатор того, является ли буфер доступным только для чтения.3435**const char \*`format`**3637Строка, завершающаяся3839*NULL*4041, в синтаксисе модуля4243[`struct`](https://python-all.ru/2.6/library/struct.html#module-struct)4445, описывающая содержимое элементов, доступных через буфер. Если это4647*NULL*4849, то подразумевается5051`"B"`5253(беззнаковые байты).5455**int `ndim`**5657Количество измерений, которые память представляет как многомерный массив. Если оно равно 0,5859[`strides`](https://python-all.ru/2.6/c-api/buffer.html#strides)6061и6263[`suboffsets`](https://python-all.ru/2.6/c-api/buffer.html#suboffsets)6465должны быть6667*NULL*6869.7071**Py\_ssize\_t \*`shape`**7273Массив7475`Py_ssize_t`7677длиной7879[`ndim`](https://python-all.ru/2.6/c-api/buffer.html#ndim)8081, задающий форму памяти как многомерного массива. Обратите внимание, что8283`((*shape)[0] * ... * (*shape)[ndims-1])*itemsize`8485должно быть равно8687`len`8889.9091**Py\_ssize\_t \*`strides`**9293Массив9495`Py_ssize_t`9697длиной9899[`ndim`](https://python-all.ru/2.6/c-api/buffer.html#ndim)100101, задающий количество байтов, которое нужно пропустить, чтобы перейти к новому элементу в каждом измерении.102103**Py\_ssize\_t \*`suboffsets`**104105Массив `Py_ssize_t` длиной [`ndim`](https://python-all.ru/2.6/c-api/buffer.html#ndim). Если эти числа suboffset больше или равны 0, то значение, хранящееся по указанному измерению, является указателем, а значение suboffset определяет, сколько байтов добавить к указателю после разыменования. Отрицательное значение suboffset означает, что разыменование не должно выполняться (шаг в непрерывном блоке памяти).106107Вот функция, которая возвращает указатель на элемент в N-мерном массиве, на который указывает N-мерный индекс, при наличии как ненулевых strides, так и suboffsets:108109```c110void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,111 Py_ssize_t *suboffsets, Py_ssize_t *indices) {112 char *pointer = (char*)buf;113 int i;114 for (i = 0; i < ndim; i++) {115 pointer += strides[i] * indices[i];116 if (suboffsets[i] >=0 ) {117 pointer = *((char**)pointer) + suboffsets[i];118 }119 }120 return (void*)pointer;121 }122```123124**Py\_ssize\_t `itemsize`**125126Это поле хранит размер элемента (в байтах) для каждого элемента общей памяти. Технически оно не обязательно, так как его можно получить с помощью127128[`PyBuffer_SizeFromFormat()`](https://python-all.ru/2.6/c-api/buffer.html#PyBuffer_SizeFromFormat)129130, однако экспортер может знать эту информацию без разбора строки формата, и знание размера элемента необходимо для правильной интерпретации шагов. Поэтому его хранение более удобно и быстрее.131132**void \*`internal`**133134Это поле предназначено для внутреннего использования экспортирующим объектом. Например, оно может быть переинтерпретировано как целое число экспортером и использоваться для хранения флагов о том, нужно ли освобождать массивы shape, strides и suboffsets при освобождении буфера. Потребитель никогда не должен изменять это значение.135136## Функции, связанные с буферами137138**int `PyObject_CheckBuffer`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*)**139140Возвращает 1, если141142*obj*143144поддерживает буферный интерфейс, иначе 0.145146**int `PyObject_GetBuffer`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*, [Py\_buffer](https://python-all.ru/2.6/c-api/buffer.html#Py_buffer) *\*view*, int *flags*)**147148Экспортирует *obj* в [`Py_buffer`](https://python-all.ru/2.6/c-api/buffer.html#Py_buffer), *view*. Эти аргументы никогда не должны быть *NULL*. Аргумент *flags* – это битовое поле, указывающее, с каким типом буфера готов работать вызывающий код, и, следовательно, какой тип буфера экспортеру разрешено возвращать. Буферный интерфейс позволяет реализовать сложные сценарии совместного использования памяти, но некоторые вызывающие коды могут не справиться со всей сложностью и захотят проверить, сможет ли экспортер предоставить более простой способ доступа к своей памяти.149150Некоторые экспортеры могут быть не в состоянии разделять память всеми возможными способами и могут быть вынуждены генерировать исключения, чтобы сообщить некоторым потребителям, что что-то невозможно. Эти исключения должны быть `BufferError`, если только нет другого исключения, которое действительно вызывает проблему. Экспортер может использовать информацию флагов, чтобы упростить заполнение структуры [`Py_buffer`](https://python-all.ru/2.6/c-api/buffer.html#Py_buffer) значениями, отличными от значений по умолчанию, и/или вызвать ошибку, если объект не может предоставить более простой доступ к своей памяти.1511520 возвращается в случае успеха, -1 – при ошибке.153154В следующей таблице приведены возможные значения аргумента *flags*.155156| Флаг | Описание |157| --- | --- |158| `PyBUF_SIMPLE` | Это состояние флага по умолчанию. Возвращаемый буфер может иметь или не иметь память для записи. Формат данных будет считаться беззнаковыми байтами. Это «автономная» константа флага. Её никогда не нужно комбинировать с другими с помощью оператора '\|'. Экспортёр вызовет ошибку, если не сможет предоставить такой непрерывный буфер байтов. |159| `PyBUF_WRITABLE` | Возвращаемый буфер должен быть доступен для записи. Если это не так, вызывается ошибка. |160| `PyBUF_STRIDES` | Это подразумевает `PyBUF_ND`. Возвращаемый буфер должен предоставлять информацию о шагах (т.е. шаги не могут быть NULL). Используется, когда потребитель может работать со страйдед-массивами (с разрывами). Работа с шагами автоматически подразумевает, что доступна информация о форме. Экспортёр может вызвать ошибку, если страйдед-представление данных невозможно (например, без suboffsets). |161| `PyBUF_ND` | Возвращаемый буфер должен предоставлять информацию о форме. Память считается C-стиль непрерывной (последнее измерение меняется быстрее всего). Экспортёр может вызвать ошибку, если не может предоставить такой непрерывный буфер. Если этот флаг не задан, форма будет *NULL*. |162| `PyBUF_C_CONTIGUOUS` `PyBUF_F_CONTIGUOUS` `PyBUF_ANY_CONTIGUOUS` | Эти флаги указывают, что возвращаемый буфер должен быть соответственно C-непрерывным (последнее измерение меняется быстрее всего), Fortran-непрерывным (первое измерение меняется быстрее всего) или любым из них. Все эти флаги подразумевают `PyBUF_STRIDES` и гарантируют, что структура информации о шагах будет заполнена корректно. |163| `PyBUF_INDIRECT` | Этот флаг указывает, что возвращаемый буфер должен содержать информацию suboffsets (может быть NULL, если suboffsets не нужны). Используется, когда потребитель может работать с косвенной адресацией массива, подразумеваемой этими suboffsets. Этот флаг подразумевает `PyBUF_STRIDES`. |164| `PyBUF_FORMAT` | Возвращаемый буфер должен содержать настоящую информацию о формате, если этот флаг указан. Это используется, когда потребитель собирается проверять, какой именно тип данных хранится. Экспортёр всегда должен быть способен предоставить эту информацию по запросу. Если формат явно не запрошен, он должен быть возвращён как *NULL* (что означает `'B'`, то есть беззнаковые байты). |165| `PyBUF_STRIDED` | Это эквивалентно `(PyBUF_STRIDES \| PyBUF_WRITABLE)`. |166| `PyBUF_STRIDED_RO` | Это эквивалентно `(PyBUF_STRIDES)`. |167| `PyBUF_RECORDS` | Это эквивалентно `(PyBUF_STRIDES \| PyBUF_FORMAT \| PyBUF_WRITABLE)`. |168| `PyBUF_RECORDS_RO` | Это эквивалентно `(PyBUF_STRIDES \| PyBUF_FORMAT)`. |169| `PyBUF_FULL` | Это эквивалентно `(PyBUF_INDIRECT \| PyBUF_FORMAT \| PyBUF_WRITABLE)`. |170| `PyBUF_FULL_RO` | Это эквивалентно `(PyBUF_INDIRECT \| PyBUF_FORMAT)`. |171| `PyBUF_CONTIG` | Это эквивалентно `(PyBUF_ND \| PyBUF_WRITABLE)`. |172| `PyBUF_CONTIG_RO` | Это эквивалентно `(PyBUF_ND)`. |173174**void `PyBuffer_Release`([Py\_buffer](https://python-all.ru/2.6/c-api/buffer.html#Py_buffer) *\*view*)**175176Освобождает буфер177178*view*179180. Должен вызываться, когда буфер больше не используется, так как может освободить занимаемую им память.181182**Py\_ssize\_t `PyBuffer_SizeFromFormat`(const char *\**)**183184Возвращает неявный185186`~Py_buffer.itemsize`187188из форматной строки struct189190`~Py_buffer.format`191192.193194**int `PyObject_CopyToObject`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*, void *\*buf*, Py\_ssize\_t *len*, char *fortran*)**195196Копирует197198*len*199200байт данных, на которые указывает непрерывный блок памяти, на который указывает201202*buf*203204, в буфер, экспортируемый obj. Буфер, конечно, должен быть доступен для записи. Возвращает 0 в случае успеха и -1 с возбуждением исключения в случае ошибки. Если объект не имеет буфера, доступного для записи, возбуждается исключение. Если205206*fortran*207208равно209210`'F'`211212, то если объект многомерен, данные копируются в массив в стиле Fortran (первое измерение изменяется быстрее всего). Если213214*fortran*215216равно217218`'C'`219220, данные копируются в массив в стиле C (последнее измерение изменяется быстрее всего). Если221222*fortran*223224равно225226`'A'`227228, то не имеет значения, и копирование будет выполнено максимально эффективным способом.229230**int `PyBuffer_IsContiguous`([Py\_buffer](https://python-all.ru/2.6/c-api/buffer.html#Py_buffer) *\*view*, char *fortran*)**231232Возвращает 1, если память, определяемая233234*view*235236, является смежной в стиле C (237238*fortran*239240равно241242`'C'`243244) или в стиле Fortran (245246*fortran*247248равно249250`'F'`251252), или любого из них (253254*fortran*255256равно257258`'A'`259260). В противном случае возвращает 0.261262**void `PyBuffer_FillContiguousStrides`(int *ndim*, Py\_ssize\_t *\*shape*, Py\_ssize\_t *\*strides*, Py\_ssize\_t *itemsize*, char *fortran*)**263264Заполняет массив265266*strides*267268байтовыми шагами непрерывного (в стиле C, если269270*fortran*271272равно273274`'C'`275276, или в стиле Фортрана, если277278*fortran*279280равно281282`'F'`283284) массива заданной формы с заданным количеством байтов на элемент.285286**int `PyBuffer_FillInfo`([Py\_buffer](https://python-all.ru/2.6/c-api/buffer.html#Py_buffer) *\*view*, [PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*obj*, void *\*buf*, Py\_ssize\_t *len*, int *readonly*, int *infoflags*)**287288Заполняет структуру буферной информации289290*view*291292корректно для экспортёра, который может передавать только смежный блок памяти из «unsigned bytes» заданной длины. Возвращает 0 при успехе и -1 (с порождением исключения) при ошибке.293294## Объекты буфера старого стиля295296Дополнительная информация о буферном интерфейсе приведена в разделе [*Структуры буферных объектов*](https://python-all.ru/2.6/c-api/typeobj.html#buffer-structs), в описании [`PyBufferProcs`](https://python-all.ru/2.6/c-api/typeobj.html#PyBufferProcs).297298«Буферный объект» определяется в заголовочном файле `bufferobject.h` (включаемом через `Python.h`). На уровне программирования на Python эти объекты очень похожи на строковые: они поддерживают срезы, индексацию, конкатенацию и некоторые другие стандартные операции со строками. Однако их данные могут поступать из одного из двух источников: из блока памяти или из другого объекта, который экспортирует буферный интерфейс.299300Объекты буфера полезны как способ предоставления данных из интерфейса буфера другого объекта программисту на Python. Они также могут использоваться как механизм срезов с нулевым копированием. Благодаря возможности ссылаться на блок памяти, можно довольно легко предоставить любые данные программисту на Python. Память может быть большим постоянным массивом в расширении на C, сырым блоком памяти для манипуляций перед передачей в библиотеку операционной системы или использоваться для передачи структурированных данных в их родном формате в памяти.301302**`PyBufferObject`**303304Этот подтип305306[`PyObject`](https://python-all.ru/2.6/c-api/structures.html#PyObject)307308представляет буферный объект.309310**[PyTypeObject](https://python-all.ru/2.6/c-api/type.html#PyTypeObject) `PyBuffer_Type`**311312Экземпляр [`PyTypeObject`](https://python-all.ru/2.6/c-api/type.html#PyTypeObject), представляющий тип буфера Python; это тот же объект, что и `buffer` и `types.BufferType` на уровне Python.313314**int `Py_END_OF_BUFFER`**315316Эту константу можно передавать в качестве параметра317318*size*319320функциям321322[`PyBuffer_FromObject()`](https://python-all.ru/2.6/c-api/buffer.html#PyBuffer_FromObject)323324или325326[`PyBuffer_FromReadWriteObject()`](https://python-all.ru/2.6/c-api/buffer.html#PyBuffer_FromReadWriteObject)327328. Она указывает, что новый329330[`PyBufferObject`](https://python-all.ru/2.6/c-api/buffer.html#PyBufferObject)331332должен ссылаться на объект333334*base*335336от указанного337338*offset*339340до конца его экспортируемого буфера. Использование этой константы позволяет вызывающему коду не запрашивать длину у объекта341342*base*343344.345346**int `PyBuffer_Check`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*p*)**347348Возвращает true, если аргумент имеет тип349350[`PyBuffer_Type`](https://python-all.ru/2.6/c-api/buffer.html#PyBuffer_Type)351352.353354**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyBuffer_FromObject`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*base*, Py\_ssize\_t *offset*, Py\_ssize\_t *size*)**355356*Возвращаемое значение: новая ссылка.*357358Возвращает новый буферный объект только для чтения. Возбуждается [`TypeError`](https://python-all.ru/2.6/library/exceptions.html#exceptions.TypeError), если *base* не поддерживает протокол буфера только для чтения или не предоставляет ровно один сегмент буфера, и возбуждается [`ValueError`](https://python-all.ru/2.6/library/exceptions.html#exceptions.ValueError), если *offset* меньше нуля. Буфер будет содержать ссылку на объект *base*, а содержимое буфера будет ссылаться на буферный интерфейс объекта *base*, начиная с позиции *offset* и занимая *size* байт. Если *size* равно [`Py_END_OF_BUFFER`](https://python-all.ru/2.6/c-api/buffer.html#Py_END_OF_BUFFER), то содержимое нового буфера распространяется на всю длину экспортированных буферных данных объекта *base*.359360Изменено в версии 2.5: Для параметров *offset* и *size* в этой функции использовался тип `int`. Это может потребовать изменений в вашем коде для корректной поддержки 64-разрядных систем.361362**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyBuffer_FromReadWriteObject`([PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject) *\*base*, Py\_ssize\_t *offset*, Py\_ssize\_t *size*)**363364*Возвращаемое значение: новая ссылка.*365366Возвращает новый буферный объект, доступный для записи. Параметры и исключения аналогичны [`PyBuffer_FromObject()`](https://python-all.ru/2.6/c-api/buffer.html#PyBuffer_FromObject). Если объект *base* не экспортирует протокол буфера, доступного для записи, то возбуждается [`TypeError`](https://python-all.ru/2.6/library/exceptions.html#exceptions.TypeError).367368Изменено в версии 2.5: Для параметров *offset* и *size* в этой функции использовался тип `int`. Это может потребовать изменений в вашем коде для корректной поддержки 64-разрядных систем.369370**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyBuffer_FromMemory`(void *\*ptr*, Py\_ssize\_t *size*)**371372*Возвращаемое значение: новая ссылка.*373374Возвращает новый буферный объект только для чтения, который читает данные из указанного расположения в памяти с заданным размером. Вызывающий обязан гарантировать, что буфер памяти, переданный как *ptr*, не будет освобождён, пока существует возвращаемый буферный объект. Возбуждается [`ValueError`](https://python-all.ru/2.6/library/exceptions.html#exceptions.ValueError), если *size* меньше нуля. Обратите внимание, что [`Py_END_OF_BUFFER`](https://python-all.ru/2.6/c-api/buffer.html#Py_END_OF_BUFFER) *нельзя* передавать в качестве параметра *size*; в этом случае будет возбуждено [`ValueError`](https://python-all.ru/2.6/library/exceptions.html#exceptions.ValueError).375376Изменено в версии 2.5: Для параметра *size* в этой функции использовался тип `int`. Это может потребовать изменений в вашем коде для корректной поддержки 64-разрядных систем.377378**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyBuffer_FromReadWriteMemory`(void *\*ptr*, Py\_ssize\_t *size*)**379380*Возвращаемое значение: новая ссылка.*381382Аналогична [`PyBuffer_FromMemory()`](https://python-all.ru/2.6/c-api/buffer.html#PyBuffer_FromMemory), но возвращаемый буфер доступен для записи.383384Изменено в версии 2.5: Для параметра *size* в этой функции использовался тип `int`. Это может потребовать изменений в вашем коде для корректной поддержки 64-разрядных систем.385386**[PyObject](https://python-all.ru/2.6/c-api/structures.html#PyObject)\* `PyBuffer_New`(Py\_ssize\_t *size*)**387388*Возвращаемое значение: новая ссылка.*389390Return a new writable buffer object that maintains its own memory buffer of *size* bytes. [`ValueError`](https://python-all.ru/2.6/library/exceptions.html#exceptions.ValueError) is returned if *size* is not zero or positive. Note that the memory buffer (as returned by [`PyObject_AsWriteBuffer()`](https://python-all.ru/2.6/c-api/objbuffer.html#PyObject_AsWriteBuffer)) is not specifically aligned.391392Изменено в версии 2.5: Раньше эта функция использовала тип `int` для *size*. Это может потребовать изменений в вашем коде для корректной поддержки 64-битных систем.393