Документация Python неофициальный перевод

buffer.md

381 строк · 22.1 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.1/c-api/buffer.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# Протокол буфера89Некоторые объекты в Python предоставляют доступ к лежащему в основе массиву памяти или *буферу*. К таким объектам относятся встроенные [`bytes`](https://python-all.ru/3.1/library/functions.html#bytes) и [`bytearray`](https://python-all.ru/3.1/library/functions.html#bytearray), а также некоторые типы расширений, например [`array.array`](https://python-all.ru/3.1/library/array.html#array.array). Сторонние библиотеки могут определять собственные типы для специальных целей, таких как обработка изображений или численный анализ.1011Хотя каждый из этих типов имеет свою семантику, их объединяет то, что они основаны на возможно большом буфере памяти. В некоторых ситуациях желательно иметь прямой доступ к этому буферу без промежуточного копирования.1213Python предоставляет такую возможность на уровне C в виде *протокола буфера*. У этого протокола две стороны:1415- На стороне производителя тип может экспортировать «буферный интерфейс», который позволяет объектам этого типа предоставлять информацию о своём базовом буфере. Этот интерфейс описан в разделе [*Buffer Object Structures*](https://python-all.ru/3.1/c-api/typeobj.html#buffer-structs);16- На стороне потребителя доступно несколько способов получить указатель на необработанные базовые данные объекта (например, параметр метода).1718Простые объекты, такие как [`bytes`](https://python-all.ru/3.1/library/functions.html#bytes) и [`bytearray`](https://python-all.ru/3.1/library/functions.html#bytearray), предоставляют свой нижележащий буфер в байт-ориентированной форме. Возможны и другие формы; например, элементы, предоставляемые [`array.array`](https://python-all.ru/3.1/library/array.html#array.array), могут быть многобайтовыми значениями.1920Примером потребителя интерфейса буфера является метод [`write()`](https://python-all.ru/3.1/library/io.html#io.BufferedIOBase.write) файловых объектов: любой объект, способный экспортировать последовательность байтов через интерфейс буфера, может быть записан в файл. В то время как `write()` требует только доступа на чтение к внутреннему содержимому переданного ему объекта, другие методы, такие как [`readinto()`](https://python-all.ru/3.1/library/io.html#io.BufferedIOBase.readinto), требуют доступа на запись к содержимому своего аргумента. Интерфейс буфера позволяет объектам выборочно разрешать или запрещать экспорт буферов для чтения-записи и только для чтения.2122Существует два способа для потребителя буферного интерфейса получить буфер над целевым объектом:2324- вызов [`PyObject_GetBuffer()`](https://python-all.ru/3.1/c-api/buffer.html#PyObject_GetBuffer) с правильными параметрами;25- вызов [`PyArg_ParseTuple()`](https://python-all.ru/3.1/c-api/arg.html#PyArg_ParseTuple) (или одной из его разновидностей) с одним из `y*`, `w*` или `s*` [*кодов формата*](https://python-all.ru/3.1/c-api/arg.html#arg-parsing).2627В обоих случаях [`PyBuffer_Release()`](https://python-all.ru/3.1/c-api/buffer.html#PyBuffer_Release) необходимо вызвать, когда буфер больше не нужен. Несоблюдение этого может привести к различным проблемам, таким как утечка ресурсов.2829## Структура буфера3031Структуры буферов (или просто «буферы») полезны как способ предоставления бинарных данных из другого объекта программисту на Python. Их также можно использовать как механизм среза с нулевым копированием. Благодаря возможности ссылаться на блок памяти, можно довольно легко предоставить любые данные программисту на Python. Память может быть большим константным массивом в C-расширении, необработанным блоком памяти для манипуляций перед передачей в библиотеку операционной системы или использоваться для передачи структурированных данных в их родном формате в памяти.3233В отличие от большинства типов данных, предоставляемых интерпретатором Python, буферы не являются указателями на [`PyObject`](https://python-all.ru/3.1/c-api/structures.html#PyObject), а представляют собой простые структуры C. Это позволяет создавать и копировать их очень просто. Когда требуется универсальная обёртка вокруг буфера, можно создать объект [*memoryview*](https://python-all.ru/3.1/c-api/memoryview.html#memoryview-objects).3435**`Py_buffer`**3637**void \*`buf`**3839Указатель на начало памяти объекта.4041**Py\_ssize\_t `len`**4243Общая длина памяти в байтах.4445**int `readonly`**4647Индикатор того, является ли буфер доступным только для чтения.4849**const char \*`format`**5051Строка, завершающаяся5253*NULL*5455, в синтаксисе модуля5657[`struct`](https://python-all.ru/3.1/library/struct.html#module-struct)5859, описывающая содержимое элементов, доступных через буфер. Если это6061*NULL*6263, то подразумевается6465`"B"`6667(беззнаковые байты).6869**int `ndim`**7071Количество измерений, которые память представляет как многомерный массив. Если оно равно 0,7273[`strides`](https://python-all.ru/3.1/c-api/buffer.html#strides)7475и7677[`suboffsets`](https://python-all.ru/3.1/c-api/buffer.html#suboffsets)7879должны быть8081*NULL*8283.8485**Py\_ssize\_t \*`shape`**8687Массив8889`Py_ssize_t`9091длиной9293[`ndim`](https://python-all.ru/3.1/c-api/buffer.html#ndim)9495, задающий форму памяти как многомерного массива. Обратите внимание, что9697`((*shape)[0] * ... * (*shape)[ndims-1])*itemsize`9899должно быть равно100101`len`102103.104105**Py\_ssize\_t \*`strides`**106107Массив108109`Py_ssize_t`110111длиной112113[`ndim`](https://python-all.ru/3.1/c-api/buffer.html#ndim)114115, задающий количество байтов, которое нужно пропустить, чтобы перейти к новому элементу в каждом измерении.116117**Py\_ssize\_t \*`suboffsets`**118119Массив `Py_ssize_t` длиной [`ndim`](https://python-all.ru/3.1/c-api/buffer.html#ndim). Если эти числа suboffset больше или равны 0, то значение, хранящееся по указанному измерению, является указателем, а значение suboffset определяет, сколько байтов добавить к указателю после разыменования. Отрицательное значение suboffset означает, что разыменование не должно выполняться (шаг в непрерывном блоке памяти).120121Ниже приведена функция, возвращающая указатель на элемент в N-мерном массиве, на который указывает N-мерный индекс, при наличии как ненулевых шагов (strides), так и субсмещений (suboffsets):122123```c124void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,125    Py_ssize_t *suboffsets, Py_ssize_t *indices) {126    char *pointer = (char*)buf;127    int i;128    for (i = 0; i < ndim; i++) {129        pointer += strides[i] * indices[i];130        if (suboffsets[i] >=0 ) {131            pointer = *((char**)pointer) + suboffsets[i];132        }133    }134    return (void*)pointer;135 }136```137138**Py\_ssize\_t `itemsize`**139140Это поле хранит размер элемента (в байтах) для каждого элемента общей памяти. Технически оно не обязательно, так как его можно получить с помощью141142[`PyBuffer_SizeFromFormat()`](https://python-all.ru/3.1/c-api/buffer.html#PyBuffer_SizeFromFormat)143144, однако экспортер может знать эту информацию без разбора строки формата, и знание размера элемента необходимо для правильной интерпретации шагов. Поэтому его хранение более удобно и быстрее.145146**void \*`internal`**147148Это поле предназначено для внутреннего использования экспортирующим объектом. Например, оно может быть переинтерпретировано как целое число экспортером и использоваться для хранения флагов о том, нужно ли освобождать массивы shape, strides и suboffsets при освобождении буфера. Потребитель никогда не должен изменять это значение.149150## Функции, связанные с буфером151152**int `PyObject_CheckBuffer`([PyObject](https://python-all.ru/3.1/c-api/structures.html#PyObject) *\*obj*)**153154Возвращает 1, если155156*obj*157158поддерживает интерфейс буфера, иначе 0. Если возвращается 1, это не гарантирует, что159160[`PyObject_GetBuffer()`](https://python-all.ru/3.1/c-api/buffer.html#PyObject_GetBuffer)161162выполнится успешно.163164**int `PyObject_GetBuffer`([PyObject](https://python-all.ru/3.1/c-api/structures.html#PyObject) *\*obj*, [Py\_buffer](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer) *\*view*, int *flags*)**165166Экспортирует представление некоторых внутренних данных целевого объекта *obj*. *obj* не должен быть NULL, а *view* должен указывать на существующую структуру [`Py_buffer`](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer), выделенную вызывающим (в большинстве случаев эта функция просто объявляет локальную переменную типа [`Py_buffer`](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer)). Аргумент *flags* – это битовое поле, указывающее, какой тип буфера запрашивается. Интерфейс буфера допускает сложные варианты расположения памяти; однако некоторые вызывающие не захотят обрабатывать всю сложность и вместо этого запросят простое представление целевого объекта (используя [`PyBUF_SIMPLE`](https://python-all.ru/3.1/c-api/buffer.html#PyBUF_SIMPLE) для представления только для чтения и [`PyBUF_WRITABLE`](https://python-all.ru/3.1/c-api/buffer.html#PyBUF_WRITABLE) для представления для чтения и записи).167168Некоторые экспортеры могут не иметь возможности предоставить память любым способом и могут вызывать ошибки, чтобы сообщить некоторым потребителям, что что-то невозможно. Эти ошибки должны быть [`BufferError`](https://python-all.ru/3.1/library/exceptions.html#BufferError), если только нет другой ошибки, которая на самом деле является причиной проблемы. Экспортер может использовать информацию о флагах, чтобы упростить, какая часть структуры [`Py_buffer`](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer) заполняется нестандартными значениями, и/или вызвать ошибку, если объект не поддерживает более простое представление своей памяти.169170В случае успеха возвращается 0, а структура *view* заполняется полезными значениями. В случае ошибки возвращается -1 и возбуждается исключение; структура *view* остаётся в неопределённом состоянии.171172Ниже перечислены возможные значения аргумента *flags*.173174**`PyBUF_SIMPLE`**175176Это флаг по умолчанию. Возвращаемый буфер предоставляет область памяти только для чтения. Предполагается, что формат данных – необработанные беззнаковые байты, без какой-либо определённой структуры. Это «автономная» константа флага. Её никогда не нужно объединять с другими через ‘|’. Экспортер вызовет ошибку, если не сможет предоставить такой непрерывный байтовый буфер.177178**`PyBUF_WRITABLE`**179180Как181182[`PyBUF_SIMPLE`](https://python-all.ru/3.1/c-api/buffer.html#PyBUF_SIMPLE)183184, но возвращаемый буфер доступен для записи. Если экспортер не поддерживает буферы для записи, возникает ошибка.185186**`PyBUF_STRIDES`**187188Это подразумевает189190[`PyBUF_ND`](https://python-all.ru/3.1/c-api/buffer.html#PyBUF_ND)191192. Возвращаемый буфер должен предоставлять информацию о шагах (т.е. шаги не могут быть NULL). Это используется, когда потребитель может работать со страйдед-массивами (несмежными по измерениям). Обработка шагов автоматически подразумевает возможность обработки формы. Экспортер может вызвать ошибку, если страйдед-представление данных невозможно (например, без подсмещений).193194**`PyBUF_ND`**195196Возвращаемый буфер должен предоставлять информацию о форме. Память будет считаться непрерывной в стиле C (последнее измерение изменяется быстрее всего). Экспортер может вызвать ошибку, если не может предоставить такой непрерывный буфер. Если этот флаг не задан, форма будет197198*NULL*199200.201202**`PyBUF_C_CONTIGUOUS`**203204**`PyBUF_F_CONTIGUOUS`**205206**`PyBUF_ANY_CONTIGUOUS`**207208Эти флаги указывают, что возвращаемый буфер должен быть соответственно C-непрерывным (последнее измерение изменяется быстрее всего), Fortran-непрерывным (первое измерение изменяется быстрее всего) или любым из них. Все эти флаги подразумевают209210[`PyBUF_STRIDES`](https://python-all.ru/3.1/c-api/buffer.html#PyBUF_STRIDES)211212и гарантируют, что структура информации о шагах буфера будет заполнена корректно.213214**`PyBUF_INDIRECT`**215216Этот флаг указывает, что возвращаемый буфер должен содержать информацию о подсмещениях (может быть NULL, если подсмещения не нужны). Это может использоваться, когда потребитель может обрабатывать косвенную ссылку на массив, подразумеваемую этими подсмещениями. Этот флаг подразумевает217218[`PyBUF_STRIDES`](https://python-all.ru/3.1/c-api/buffer.html#PyBUF_STRIDES)219220.221222**`PyBUF_FORMAT`**223224Возвращаемый буфер должен содержать настоящую информацию о формате, если этот флаг передан. Это используется, когда потребитель собирается проверять, какой «тип» данных на самом деле хранится. Экспортер всегда должен предоставлять эту информацию по запросу. Если формат явно не запрошен, формат должен быть возвращен как225226*NULL*227228(что означает229230`'B'`231232, или беззнаковые байты).233234**`PyBUF_STRIDED`**235236Это эквивалентно237238`(PyBUF_STRIDES | PyBUF_WRITABLE)`239240.241242**`PyBUF_STRIDED_RO`**243244Это эквивалентно245246`(PyBUF_STRIDES)`247248.249250**`PyBUF_RECORDS`**251252Это эквивалентно253254`(PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)`255256.257258**`PyBUF_RECORDS_RO`**259260Это эквивалентно261262`(PyBUF_STRIDES | PyBUF_FORMAT)`263264.265266**`PyBUF_FULL`**267268Это эквивалентно269270`(PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)`271272.273274**`PyBUF_FULL_RO`**275276Это эквивалентно277278`(PyBUF_INDIRECT | PyBUF_FORMAT)`279280.281282**`PyBUF_CONTIG`**283284Это эквивалентно285286`(PyBUF_ND | PyBUF_WRITABLE)`287288.289290**`PyBUF_CONTIG_RO`**291292Это эквивалентно293294`(PyBUF_ND)`295296.297298**void `PyBuffer_Release`([Py\_buffer](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer) *\*view*)**299300Освобождает буфер301302*view*303304. Эту функцию следует вызывать, когда буфер больше не используется, так как она может освободить память из него.305306**Py\_ssize\_t `PyBuffer_SizeFromFormat`(const char *\**)**307308Возвращает неявный309310`~Py_buffer.itemsize`311312из форматной строки struct313314`~Py_buffer.format`315316.317318**int `PyBuffer_IsContiguous`([Py\_buffer](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer) *\*view*, char *fortran*)**319320Возвращает 1, если память, определяемая321322*view*323324, является смежной в стиле C (325326*fortran*327328равно329330`'C'`331332) или в стиле Fortran (333334*fortran*335336равно337338`'F'`339340), или любого из них (341342*fortran*343344равно345346`'A'`347348). В противном случае возвращает 0.349350**void `PyBuffer_FillContiguousStrides`(int *ndim*, Py\_ssize\_t *\*shape*, Py\_ssize\_t *\*strides*, Py\_ssize\_t *itemsize*, char *fortran*)**351352Заполняет массив353354*strides*355356байтовыми шагами смежного массива (в стиле C, если357358*fortran*359360равно361362`'C'`363364, или в стиле Fortran, если365366*fortran*367368равно369370`'F'`371372) массива заданной формы с заданным количеством байт на элемент.373374**int `PyBuffer_FillInfo`([Py\_buffer](https://python-all.ru/3.1/c-api/buffer.html#Py_buffer) *\*view*, [PyObject](https://python-all.ru/3.1/c-api/structures.html#PyObject) *\*obj*, void *\*buf*, Py\_ssize\_t *len*, int *readonly*, int *infoflags*)**375376Заполняет структуру буферной информации377378*view*379380корректно для экспортёра, который может передавать только смежный блок памяти из «unsigned bytes» заданной длины. Возвращает 0 при успехе и -1 (с порождением исключения) при ошибке.381