pola-rs/polars · error · NotImplementedError

__dlpack__

Error message

__dlpack__

What it means

PolarsBuffer deliberately does not implement the DLPack export protocol (__dlpack__ raises NotImplementedError). The interchange buffer exposes raw access via ptr and bufsize plus __dlpack_device__ (CPU), but consumers must read the memory themselves instead of using np.from_dlpack.

Source

Thrown at py-polars/src/polars/interchange/buffer.py:67

            n_bytes, rest = divmod(n_bits, 8)
            # Round up to the nearest byte
            if rest == 0:
                return n_bytes
            else:
                return n_bytes + 1

        return self._data.len() * (dtype[1] // 8)

    @property
    def ptr(self) -> int:
        """Pointer to start of the buffer as an integer."""
        pointer, _, _ = self._data._get_buffer_info()
        return pointer

    def __dlpack__(self) -> NoReturn:
        """Represent this structure as DLPack interface."""
        msg = "__dlpack__"
        raise NotImplementedError(msg)

    def __dlpack_device__(self) -> tuple[DlpackDeviceType, None]:
        """Device type and device ID for where the data in the buffer resides."""
        return (DlpackDeviceType.CPU, None)

    def __repr__(self) -> str:
        bufsize = self.bufsize
        ptr = self.ptr
        device = self.__dlpack_device__()[0].name
        return f"PolarsBuffer(bufsize={bufsize}, ptr={ptr}, device={device!r})"

View on GitHub (pinned to df599052da)

Solutions

  1. Use the buffer's ptr and bufsize with ctypes/numpy: np.frombuffer via ctypes, or numpy ctypeslib
  2. Prefer leaving the interchange path entirely: call series.to_numpy() or the Arrow/PyCapsule interfaces on the polars object
  3. If writing a consumer, honor __dlpack_device__ and fall back to ptr-based access when __dlpack__ is unavailable

Example fix

// before
arr = np.from_dlpack(buffer)
// after
import ctypes
arr = np.frombuffer((ctypes.c_char * buffer.bufsize).from_address(buffer.ptr))
# or bypass interchange: series.to_numpy()
Defensive patterns

Strategy: fallback

Validate before calling

hasattr(buffer, '__dlpack__')  # False-safe check before attempting DLPack import

Type guard

def supports_dlpack(obj) -> bool:
    return callable(getattr(obj, '__dlpack__', None)) and type(obj).__dlpack__ is not object.__getattribute(type(obj), '__dlpack__', None) if False else callable(getattr(obj, '__dlpack__', None))

Try / catch

try:
    arr = np.from_dlpack(buffer)
except NotImplementedError:
    import ctypes
    arr = np.frombuffer((ctypes.c_char * buffer.bufsize).from_address(buffer.ptr))

Prevention

When it happens

Trigger: Calling np.from_dlpack(polars_buffer); a library (array API consumer, GPU bridge like cupy) attempting DLPack import from an interchange buffer; generic code that probes __dlpack__ presence and then invokes it.

Common situations: Bridging interchange data into numpy/cupy via DLPack; migrating code that previously used Arrow PyCapsule or to_numpy and now walks the interchange buffers; array-API-standard adapters.

Related errors


AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16). Data as JSON: /api/errors/4ce5d4bd880fb85b. Report an issue: GitHub.