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

buffer.md

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

1> **Источник:** https://python-all.ru/3.2/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.2/library/functions.html#bytes) и [`bytearray`](https://python-all.ru/3.2/library/functions.html#bytearray), а также некоторые типы расширений, например [`array.array`](https://python-all.ru/3.2/library/array.html#array.array). Сторонние библиотеки могут определять собственные типы для специальных целей, таких как обработка изображений или численный анализ.1011Хотя каждый из этих типов имеет свою семантику, их объединяет то, что они основаны на возможно большом буфере памяти. В некоторых ситуациях желательно иметь прямой доступ к этому буферу без промежуточного копирования.1213Python предоставляет такую возможность на уровне C в виде [*буферного протокола*](https://python-all.ru/3.2/c-api/buffer.html#bufferobjects). У этого протокола есть две стороны:1415- На стороне производителя тип может экспортировать «буферный интерфейс», который позволяет объектам этого типа предоставлять информацию о своём базовом буфере. Этот интерфейс описан в разделе [*Buffer Object Structures*](https://python-all.ru/3.2/c-api/typeobj.html#buffer-structs);16- На стороне потребителя доступно несколько способов получить указатель на необработанные базовые данные объекта (например, параметр метода).1718Простые объекты, такие как [`bytes`](https://python-all.ru/3.2/library/functions.html#bytes) и [`bytearray`](https://python-all.ru/3.2/library/functions.html#bytearray), предоставляют свой нижележащий буфер в байт-ориентированной форме. Возможны и другие формы; например, элементы, предоставляемые [`array.array`](https://python-all.ru/3.2/library/array.html#array.array), могут быть многобайтовыми значениями.1920Примером потребителя интерфейса буфера является метод [`write()`](https://python-all.ru/3.2/library/io.html#io.BufferedIOBase.write) файловых объектов: любой объект, способный экспортировать последовательность байтов через интерфейс буфера, может быть записан в файл. В то время как `write()` требует только доступа на чтение к внутреннему содержимому переданного ему объекта, другие методы, такие как [`readinto()`](https://python-all.ru/3.2/library/io.html#io.BufferedIOBase.readinto), требуют доступа на запись к содержимому своего аргумента. Интерфейс буфера позволяет объектам выборочно разрешать или запрещать экспорт буферов для чтения-записи и только для чтения.2122Существует два способа для потребителя буферного интерфейса получить буфер над целевым объектом:2324- вызов [`PyObject_GetBuffer()`](https://python-all.ru/3.2/c-api/buffer.html#PyObject_GetBuffer) с правильными параметрами;25- вызов [`PyArg_ParseTuple()`](https://python-all.ru/3.2/c-api/arg.html#PyArg_ParseTuple) (или одной из его разновидностей) с одним из `y*`, `w*` или `s*` [*кодов формата*](https://python-all.ru/3.2/c-api/arg.html#arg-parsing).2627В обоих случаях [`PyBuffer_Release()`](https://python-all.ru/3.2/c-api/buffer.html#PyBuffer_Release) необходимо вызвать, когда буфер больше не нужен. Несоблюдение этого может привести к различным проблемам, таким как утечка ресурсов.2829## Структура буфера3031Структуры буферов (или просто «буферы») полезны как способ предоставления бинарных данных из другого объекта программисту на Python. Их также можно использовать как механизм среза с нулевым копированием. Благодаря возможности ссылаться на блок памяти, можно довольно легко предоставить любые данные программисту на Python. Память может быть большим константным массивом в C-расширении, необработанным блоком памяти для манипуляций перед передачей в библиотеку операционной системы или использоваться для передачи структурированных данных в их родном формате в памяти.3233В отличие от большинства типов данных, предоставляемых интерпретатором Python, буферы не являются указателями на [`PyObject`](https://python-all.ru/3.2/c-api/structures.html#PyObject), а представляют собой простые структуры C. Это позволяет создавать и копировать их очень просто. Когда требуется универсальная обёртка вокруг буфера, можно создать объект [*memoryview*](https://python-all.ru/3.2/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Строка, завершающаяся *NULL*, в синтаксисе модуля [`struct`](https://python-all.ru/3.2/library/struct.html#module-struct), описывающая содержимое элементов, доступных через буфер. Если это *NULL*, то подразумевается `"B"` (беззнаковые байты).5253**int `ndim`**5455Количество измерений, которые память представляет в виде многомерного массива. Если оно равно 0, то `strides` и `suboffsets` должны быть *NULL*.5657**Py\_ssize\_t \*`shape`**5859Массив из `Py_ssize_t` длиной `ndim`, задающий форму памяти в виде многомерного массива. Обратите внимание, что `((*shape)[0] * ... * (*shape)[ndims-1])*itemsize` должно быть равно `len`.6061**Py\_ssize\_t \*`strides`**6263Массив из `Py_ssize_t` длиной `ndim`, задающий количество байтов, которое нужно пропустить, чтобы перейти к новому элементу в каждом измерении.6465**Py\_ssize\_t \*`suboffsets`**6667Массив из `Py_ssize_t` длиной `ndim`. Если эти значения смещений больше или равны 0, то значение, хранящееся вдоль указанного измерения, является указателем, а значение смещения указывает, сколько байтов нужно добавить к указателю после разыменования. Отрицательное значение смещения означает, что разыменование не требуется (шаг в непрерывном блоке памяти).6869Ниже приведена функция, возвращающая указатель на элемент в N-мерном массиве, на который указывает N-мерный индекс, при наличии как ненулевых шагов (strides), так и субсмещений (suboffsets):7071```c72void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,73    Py_ssize_t *suboffsets, Py_ssize_t *indices) {74    char *pointer = (char*)buf;75    int i;76    for (i = 0; i < ndim; i++) {77        pointer += strides[i] * indices[i];78        if (suboffsets[i] >=0 ) {79            pointer = *((char**)pointer) + suboffsets[i];80        }81    }82    return (void*)pointer;83 }84```8586**Py\_ssize\_t `itemsize`**8788Это поле хранит размер элемента (в байтах) для каждого элемента общей памяти. Технически оно не обязательно, так как его можно получить с помощью [`PyBuffer_SizeFromFormat()`](https://python-all.ru/3.2/c-api/buffer.html#PyBuffer_SizeFromFormat), однако экспортер может знать эту информацию без разбора строки формата, и знание размера элемента необходимо для правильной интерпретации шагов. Поэтому его хранение более удобно и быстрее.8990**void \*`internal`**9192Это поле предназначено для внутреннего использования экспортирующим объектом. Например, оно может быть переинтерпретировано как целое число экспортером и использоваться для хранения флагов о том, нужно ли освобождать массивы shape, strides и suboffsets при освобождении буфера. Потребитель никогда не должен изменять это значение.9394## Функции, связанные с буфером9596#### `int PyObject_CheckBuffer(PyObject *obj)`9798Возвращает 1, если *obj* поддерживает интерфейс буфера, иначе 0. Если возвращается 1, это не гарантирует, что [`PyObject_GetBuffer()`](https://python-all.ru/3.2/c-api/buffer.html#PyObject_GetBuffer) выполнится успешно.99100#### `int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)`101102Экспортирует представление некоторых внутренних данных целевого объекта *obj*. *obj* не должен быть NULL, а *view* должен указывать на существующую структуру [`Py_buffer`](https://python-all.ru/3.2/c-api/buffer.html#Py_buffer), выделенную вызывающим (в большинстве случаев эта функция просто объявляет локальную переменную типа [`Py_buffer`](https://python-all.ru/3.2/c-api/buffer.html#Py_buffer)). Аргумент *flags* – это битовое поле, указывающее, какой тип буфера запрашивается. Интерфейс буфера допускает сложные варианты расположения памяти; однако некоторые вызывающие не захотят обрабатывать всю сложность и вместо этого запросят простое представление целевого объекта (используя [`PyBUF_SIMPLE`](https://python-all.ru/3.2/c-api/buffer.html#PyBUF_SIMPLE) для представления только для чтения и [`PyBUF_WRITABLE`](https://python-all.ru/3.2/c-api/buffer.html#PyBUF_WRITABLE) для представления для чтения и записи).103104Некоторые экспортеры могут не иметь возможности предоставить память любым способом и могут вызывать ошибки, чтобы сообщить некоторым потребителям, что что-то невозможно. Эти ошибки должны быть [`BufferError`](https://python-all.ru/3.2/library/exceptions.html#BufferError), если только нет другой ошибки, которая на самом деле является причиной проблемы. Экспортер может использовать информацию о флагах, чтобы упростить, какая часть структуры [`Py_buffer`](https://python-all.ru/3.2/c-api/buffer.html#Py_buffer) заполняется нестандартными значениями, и/или вызвать ошибку, если объект не поддерживает более простое представление своей памяти.105106В случае успеха возвращается 0, а структура *view* заполняется полезными значениями. В случае ошибки возвращается -1 и возбуждается исключение; структура *view* остаётся в неопределённом состоянии.107108Ниже перечислены возможные значения аргумента *flags*.109110**`PyBUF_SIMPLE`**111112Это флаг по умолчанию. Возвращаемый буфер предоставляет область памяти только для чтения. Предполагается, что формат данных – необработанные беззнаковые байты, без какой-либо определённой структуры. Это «автономная» константа флага. Её никогда не нужно объединять с другими через ‘|’. Экспортер вызовет ошибку, если не сможет предоставить такой непрерывный байтовый буфер.113114**`PyBUF_WRITABLE`**115116Как [`PyBUF_SIMPLE`](https://python-all.ru/3.2/c-api/buffer.html#PyBUF_SIMPLE), но возвращаемый буфер доступен для записи. Если экспортер не поддерживает буферы для записи, возникает ошибка.117118**`PyBUF_STRIDES`**119120Это подразумевает [`PyBUF_ND`](https://python-all.ru/3.2/c-api/buffer.html#PyBUF_ND). Возвращаемый буфер должен предоставлять информацию о шагах (т.е. шаги не могут быть NULL). Это используется, когда потребитель может работать со страйдед-массивами (несмежными по измерениям). Обработка шагов автоматически подразумевает возможность обработки формы. Экспортер может вызвать ошибку, если страйдед-представление данных невозможно (например, без подсмещений).121122**`PyBUF_ND`**123124Возвращаемый буфер должен предоставлять информацию о форме. Память будет считаться непрерывной в стиле C (последнее измерение изменяется быстрее всего). Экспортер может вызвать ошибку, если не может предоставить такой непрерывный буфер. Если этот флаг не задан, форма будет *NULL*.125126**`PyBUF_C_CONTIGUOUS`**127128**`PyBUF_F_CONTIGUOUS`**129130**`PyBUF_ANY_CONTIGUOUS`**131132Эти флаги указывают, что возвращаемый буфер должен быть соответственно C-непрерывным (последнее измерение изменяется быстрее всего), Fortran-непрерывным (первое измерение изменяется быстрее всего) или любым из них. Все эти флаги подразумевают [`PyBUF_STRIDES`](https://python-all.ru/3.2/c-api/buffer.html#PyBUF_STRIDES) и гарантируют, что структура информации о шагах буфера будет заполнена корректно.133134**`PyBUF_INDIRECT`**135136Этот флаг указывает, что возвращаемый буфер должен содержать информацию о подсмещениях (может быть NULL, если подсмещения не нужны). Это может использоваться, когда потребитель может обрабатывать косвенную ссылку на массив, подразумеваемую этими подсмещениями. Этот флаг подразумевает [`PyBUF_STRIDES`](https://python-all.ru/3.2/c-api/buffer.html#PyBUF_STRIDES).137138**`PyBUF_FORMAT`**139140Возвращаемый буфер должен содержать настоящую информацию о формате, если этот флаг передан. Это используется, когда потребитель собирается проверять, какой «тип» данных на самом деле хранится. Экспортер всегда должен предоставлять эту информацию по запросу. Если формат явно не запрошен, формат должен быть возвращен как *NULL* (что означает `'B'`, или беззнаковые байты).141142**`PyBUF_STRIDED`**143144Это эквивалентно `(PyBUF_STRIDES | PyBUF_WRITABLE)`.145146**`PyBUF_STRIDED_RO`**147148Это эквивалентно `(PyBUF_STRIDES)`.149150**`PyBUF_RECORDS`**151152Это эквивалентно `(PyBUF_STRIDES | PyBUF_FORMAT | PyBUF_WRITABLE)`.153154**`PyBUF_RECORDS_RO`**155156Это эквивалентно `(PyBUF_STRIDES | PyBUF_FORMAT)`.157158**`PyBUF_FULL`**159160Это эквивалентно `(PyBUF_INDIRECT | PyBUF_FORMAT | PyBUF_WRITABLE)`.161162**`PyBUF_FULL_RO`**163164Это эквивалентно `(PyBUF_INDIRECT | PyBUF_FORMAT)`.165166**`PyBUF_CONTIG`**167168Это эквивалентно `(PyBUF_ND | PyBUF_WRITABLE)`.169170**`PyBUF_CONTIG_RO`**171172Это эквивалентно `(PyBUF_ND)`.173174#### `void PyBuffer_Release(Py_buffer *view)`175176Освобождает буфер *view*. Эту функцию следует вызывать, когда буфер больше не используется, так как она может освободить память из него.177178#### `Py_ssize_t PyBuffer_SizeFromFormat(const char *)`179180Возвращает подразумеваемый [`itemsize`](https://python-all.ru/3.2/c-api/buffer.html#Py_buffer.itemsize) из строки формата struct `format`.181182#### `int PyBuffer_IsContiguous(Py_buffer *view, char fortran)`183184Возвращает 1, если память, определяемая *view*, является смежной в стиле C (*fortran* равно `'C'`) или в стиле Fortran (*fortran* равно `'F'`), или любого из них (*fortran* равно `'A'`). В противном случае возвращает 0.185186#### `void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char fortran)`187188Заполняет массив *strides* байтовыми шагами смежного массива (в стиле C, если *fortran* равно `'C'`, или в стиле Fortran, если *fortran* равно `'F'`) массива заданной формы с заданным количеством байт на элемент.189190#### `int PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len, int readonly, int infoflags)`191192Заполняет структуру буферной информации *view* корректно для экспортёра, который может передавать только смежный блок памяти из «unsigned bytes» заданной длины. Возвращает 0 при успехе и -1 (с порождением исключения) при ошибке.193