blob: 0f26e440c24478dc5a22fcffd526b7715d9f74fd [file] [log] [blame]
<!DOCTYPE html>
<html lang="en" data-content_root="../../" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>The Arrow PyCapsule Interface &#8212; Apache Arrow v23.0.0.dev39</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "";
</script>
<!--
this give us a css class that will be invisible only if js is disabled
-->
<noscript>
<style>
.pst-js-only { display: none !important; }
</style>
</noscript>
<!-- Loaded before other Sphinx assets -->
<link href="../../_static/styles/theme.css?digest=8878045cc6db502f8baf" rel="stylesheet" />
<link href="../../_static/styles/pydata-sphinx-theme.css?digest=8878045cc6db502f8baf" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css?v=03e43079" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css?v=76b2166b" />
<link rel="stylesheet" type="text/css" href="../../_static/sphinx-design.min.css?v=95c83b7e" />
<link rel="stylesheet" type="text/css" href="../../_static/theme_overrides.css?v=8dcd28dc" />
<!-- So that users can add custom icons -->
<script src="../../_static/scripts/fontawesome.js?digest=8878045cc6db502f8baf"></script>
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../../_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf" />
<link rel="preload" as="script" href="../../_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf" />
<script src="../../_static/documentation_options.js?v=d3a452a1"></script>
<script src="../../_static/doctools.js?v=9bcbadda"></script>
<script src="../../_static/sphinx_highlight.js?v=dc90522c"></script>
<script src="../../_static/clipboard.min.js?v=a7894cd8"></script>
<script src="../../_static/copybutton.js?v=3bb21c8c"></script>
<script src="../../_static/design-tabs.js?v=f930bc37"></script>
<script>DOCUMENTATION_OPTIONS.pagename = 'format/CDataInterface/PyCapsuleInterface';</script>
<script>
DOCUMENTATION_OPTIONS.theme_version = '0.16.1';
DOCUMENTATION_OPTIONS.theme_switcher_json_url = '/docs/_static/versions.json';
DOCUMENTATION_OPTIONS.theme_switcher_version_match = 'dev/';
DOCUMENTATION_OPTIONS.show_version_warning_banner =
true;
</script>
<link rel="canonical" href="https://arrow.apache.org/docs/format/CDataInterface/PyCapsuleInterface.html" />
<link rel="icon" href="../../_static/favicon.ico"/>
<link rel="index" title="Index" href="../../genindex.html" />
<link rel="search" title="Search" href="../../search.html" />
<link rel="next" title="The Arrow C stream interface" href="../CStreamInterface.html" />
<link rel="prev" title="The Arrow C data interface" href="../CDataInterface.html" />
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="docsearch:language" content="en"/>
<meta name="docsearch:version" content="23.0.0.dev39" />
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
/* We explicitly disable cookie tracking to avoid privacy issues */
_paq.push(['disableCookies']);
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.apache.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '20']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<!-- End Matomo Code -->
</head>
<body data-bs-spy="scroll" data-bs-target=".bd-toc-nav" data-offset="180" data-bs-root-margin="0px 0px -60%" data-default-mode="">
<div id="pst-skip-link" class="skip-link d-print-none"><a href="#main-content">Skip to main content</a></div>
<div id="pst-scroll-pixel-helper"></div>
<button type="button" class="btn rounded-pill" id="pst-back-to-top">
<i class="fa-solid fa-arrow-up"></i>Back to top</button>
<dialog id="pst-search-dialog">
<form class="bd-search d-flex align-items-center"
action="../../search.html"
method="get">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="search"
class="form-control"
name="q"
placeholder="Search the docs ..."
aria-label="Search the docs ..."
autocomplete="off"
autocorrect="off"
autocapitalize="off"
spellcheck="false"/>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd>K</kbd></span>
</form>
</dialog>
<div class="pst-async-banner-revealer d-none">
<aside id="bd-header-version-warning" class="d-none d-print-none" aria-label="Version warning"></aside>
</div>
<header class="bd-header navbar navbar-expand-lg bd-navbar d-print-none">
<div class="bd-header__inner bd-page-width">
<button class="pst-navbar-icon sidebar-toggle primary-toggle" aria-label="Site navigation">
<span class="fa-solid fa-bars"></span>
</button>
<div class=" navbar-header-items__start">
<div class="navbar-item">
<a class="navbar-brand logo" href="../../index.html">
<img src="../../_static/arrow.png" class="logo__image only-light" alt="Apache Arrow v23.0.0.dev39 - Home"/>
<img src="../../_static/arrow-dark.png" class="logo__image only-dark pst-js-only" alt="Apache Arrow v23.0.0.dev39 - Home"/>
</a></div>
</div>
<div class=" navbar-header-items">
<div class="me-auto navbar-header-items__center">
<div class="navbar-item">
<nav>
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item current active">
<a class="nav-link nav-internal" href="../index.html">
Specifications
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../developers/index.html">
Development
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../implementations.html">
Implementations
</a>
</li>
</ul>
</nav></div>
</div>
<div class="navbar-header-items__end">
<div class="navbar-item navbar-persistent--container">
<button class="btn search-button-field search-button__button pst-js-only" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
</div>
<div class="navbar-item"><div class="kapa-ai-bot">
<script
async
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id="9db461d5-ac77-4b3f-a5c5-75efa78339d2"
data-project-name="Apache Arrow"
data-project-color="#000000"
data-project-logo="https://arrow.apache.org/img/arrow-logo_chevrons_white-txt_black-bg.png"
data-modal-disclaimer="This is a custom LLM with access to all [Arrow documentation](https://arrow.apache.org/docs/). Please include the language you are using in your question, e.g., Python, C++, Java, R, etc."
data-consent-required="true"
data-user-analytics-cookie-enabled="false"
data-consent-screen-disclaimer="By clicking &quot;I agree, let's chat&quot;, you consent to the use of the AI assistant in accordance with kapa.ai's [Privacy Policy](https://www.kapa.ai/content/privacy-policy). This service uses reCAPTCHA, which requires your consent to Google's [Privacy Policy](https://policies.google.com/privacy) and [Terms of Service](https://policies.google.com/terms). By proceeding, you explicitly agree to both kapa.ai's and Google's privacy policies."
></script>
</div>
</div>
<div class="navbar-item">
<div class="version-switcher__container dropdown pst-js-only">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-2"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-2"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-2">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div></div>
<div class="navbar-item">
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label="Color mode" data-bs-title="Color mode" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="theme-switch fa-solid fa-sun fa-lg" data-mode="light" title="Light"></i>
<i class="theme-switch fa-solid fa-moon fa-lg" data-mode="dark" title="Dark"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode="auto" title="System Settings"></i>
</button></div>
<div class="navbar-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://www.linkedin.com/company/apache-arrow/" title="LinkedIn" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-linkedin fa-lg" aria-hidden="true"></i>
<span class="sr-only">LinkedIn</span></a>
</li>
<li class="nav-item">
<a href="https://bsky.app/profile/arrow.apache.org" title="BlueSky" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-bluesky fa-lg" aria-hidden="true"></i>
<span class="sr-only">BlueSky</span></a>
</li>
</ul></div>
</div>
</div>
<div class="navbar-persistent--mobile">
<button class="btn search-button-field search-button__button pst-js-only" title="Search" aria-label="Search" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="fa-solid fa-magnifying-glass"></i>
<span class="search-button__default-text">Search</span>
<span class="search-button__kbd-shortcut"><kbd class="kbd-shortcut__modifier">Ctrl</kbd>+<kbd class="kbd-shortcut__modifier">K</kbd></span>
</button>
</div>
<button class="pst-navbar-icon sidebar-toggle secondary-toggle" aria-label="On this page">
<span class="fa-solid fa-outdent"></span>
</button>
</div>
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<dialog id="pst-primary-sidebar-modal"></dialog>
<div id="pst-primary-sidebar" class="bd-sidebar-primary bd-sidebar">
<div class="sidebar-header-items sidebar-primary__section">
<div class="sidebar-header-items__center">
<div class="navbar-item">
<nav>
<ul class="bd-navbar-elements navbar-nav">
<li class="nav-item current active">
<a class="nav-link nav-internal" href="../index.html">
Specifications
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../developers/index.html">
Development
</a>
</li>
<li class="nav-item ">
<a class="nav-link nav-internal" href="../../implementations.html">
Implementations
</a>
</li>
</ul>
</nav></div>
</div>
<div class="sidebar-header-items__end">
<div class="navbar-item"><div class="kapa-ai-bot">
<script
async
src="https://widget.kapa.ai/kapa-widget.bundle.js"
data-website-id="9db461d5-ac77-4b3f-a5c5-75efa78339d2"
data-project-name="Apache Arrow"
data-project-color="#000000"
data-project-logo="https://arrow.apache.org/img/arrow-logo_chevrons_white-txt_black-bg.png"
data-modal-disclaimer="This is a custom LLM with access to all [Arrow documentation](https://arrow.apache.org/docs/). Please include the language you are using in your question, e.g., Python, C++, Java, R, etc."
data-consent-required="true"
data-user-analytics-cookie-enabled="false"
data-consent-screen-disclaimer="By clicking &quot;I agree, let's chat&quot;, you consent to the use of the AI assistant in accordance with kapa.ai's [Privacy Policy](https://www.kapa.ai/content/privacy-policy). This service uses reCAPTCHA, which requires your consent to Google's [Privacy Policy](https://policies.google.com/privacy) and [Terms of Service](https://policies.google.com/terms). By proceeding, you explicitly agree to both kapa.ai's and Google's privacy policies."
></script>
</div>
</div>
<div class="navbar-item">
<div class="version-switcher__container dropdown pst-js-only">
<button id="pst-version-switcher-button-3"
type="button"
class="version-switcher__button btn btn-sm dropdown-toggle"
data-bs-toggle="dropdown"
aria-haspopup="listbox"
aria-controls="pst-version-switcher-list-3"
aria-label="Version switcher list"
>
Choose version <!-- this text may get changed later by javascript -->
<span class="caret"></span>
</button>
<div id="pst-version-switcher-list-3"
class="version-switcher__menu dropdown-menu list-group-flush py-0"
role="listbox" aria-labelledby="pst-version-switcher-button-3">
<!-- dropdown will be populated by javascript on page load -->
</div>
</div></div>
<div class="navbar-item">
<button class="btn btn-sm nav-link pst-navbar-icon theme-switch-button pst-js-only" aria-label="Color mode" data-bs-title="Color mode" data-bs-placement="bottom" data-bs-toggle="tooltip">
<i class="theme-switch fa-solid fa-sun fa-lg" data-mode="light" title="Light"></i>
<i class="theme-switch fa-solid fa-moon fa-lg" data-mode="dark" title="Dark"></i>
<i class="theme-switch fa-solid fa-circle-half-stroke fa-lg" data-mode="auto" title="System Settings"></i>
</button></div>
<div class="navbar-item"><ul class="navbar-icon-links"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://www.linkedin.com/company/apache-arrow/" title="LinkedIn" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-linkedin fa-lg" aria-hidden="true"></i>
<span class="sr-only">LinkedIn</span></a>
</li>
<li class="nav-item">
<a href="https://bsky.app/profile/arrow.apache.org" title="BlueSky" class="nav-link pst-navbar-icon" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><i class="fa-brands fa-bluesky fa-lg" aria-hidden="true"></i>
<span class="sr-only">BlueSky</span></a>
</li>
</ul></div>
</div>
</div>
<div class="sidebar-primary-items__start sidebar-primary__section">
<div class="sidebar-primary-item">
<nav class="bd-docs-nav bd-links"
aria-label="Section Navigation">
<p class="bd-links__title" role="heading" aria-level="1">Section Navigation</p>
<div class="bd-toc-item navbar-nav"><ul class="current nav bd-sidenav">
<li class="toctree-l1"><a class="reference internal" href="../Intro.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Columnar.html">Arrow Columnar Format</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Versioning.html">Format Versioning and Stability</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Changing.html">Changing the Apache Arrow Format Specification</a></li>
<li class="toctree-l1"><a class="reference internal" href="../CanonicalExtensions.html">Canonical Extension Types</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Other.html">Other Data Structures</a></li>
<li class="toctree-l1 current active has-children"><a class="reference internal" href="../CDataInterface.html">The Arrow C data interface</a><details open="open"><summary><span class="toctree-toggle" role="presentation"><i class="fa-solid fa-chevron-down"></i></span></summary><ul class="current">
<li class="toctree-l2 current active"><a class="current reference internal" href="#">The Arrow PyCapsule Interface</a></li>
</ul>
</details></li>
<li class="toctree-l1"><a class="reference internal" href="../CStreamInterface.html">The Arrow C stream interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="../CDeviceDataInterface.html">The Arrow C Device data interface</a></li>
<li class="toctree-l1"><a class="reference internal" href="../StatisticsSchema.html">Statistics schema</a></li>
<li class="toctree-l1"><a class="reference internal" href="../DissociatedIPC.html">Dissociated IPC Protocol</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Flight.html">Arrow Flight RPC</a></li>
<li class="toctree-l1"><a class="reference internal" href="../FlightSql.html">Arrow Flight SQL</a></li>
<li class="toctree-l1"><a class="reference internal" href="../ADBC.html">ADBC: Arrow Database Connectivity</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Integration.html">Integration Testing</a></li>
<li class="toctree-l1"><a class="reference internal" href="../Glossary.html">Glossary</a></li>
</ul>
</div>
</nav></div>
</div>
<div class="sidebar-primary-items__end sidebar-primary__section">
<div class="sidebar-primary-item">
<div id="ethical-ad-placement"
class="flat"
data-ea-publisher="readthedocs"
data-ea-type="readthedocs-sidebar"
data-ea-manual="true">
</div></div>
</div>
</div>
<main id="main-content" class="bd-main" role="main">
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article d-print-none">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item">
<nav aria-label="Breadcrumb" class="d-print-none">
<ul class="bd-breadcrumbs">
<li class="breadcrumb-item breadcrumb-home">
<a href="../../index.html" class="nav-link" aria-label="Home">
<i class="fa-solid fa-home"></i>
</a>
</li>
<li class="breadcrumb-item"><a href="../index.html" class="nav-link">Specifications</a></li>
<li class="breadcrumb-item"><a href="../CDataInterface.html" class="nav-link">The Arrow C data interface</a></li>
<li class="breadcrumb-item active" aria-current="page"><span class="ellipsis">The Arrow PyCapsule Interface</span></li>
</ul>
</nav>
</div>
</div>
</div>
</div>
<div id="searchbox"></div>
<article class="bd-article">
<section id="the-arrow-pycapsule-interface">
<span id="arrow-pycapsule-interface"></span><h1>The Arrow PyCapsule Interface<a class="headerlink" href="#the-arrow-pycapsule-interface" title="Link to this heading">#</a></h1>
<section id="rationale">
<h2>Rationale<a class="headerlink" href="#rationale" title="Link to this heading">#</a></h2>
<p>The <a class="reference internal" href="../CDataInterface.html#c-data-interface"><span class="std std-ref">C data interface</span></a>, <a class="reference internal" href="../CStreamInterface.html#c-stream-interface"><span class="std std-ref">C stream interface</span></a>
and <a class="reference internal" href="../CDeviceDataInterface.html#c-device-data-interface"><span class="std std-ref">C device interface</span></a> allow moving Arrow data between
different implementations of Arrow. However, these interfaces don’t specify how
Python libraries should expose these structs to other libraries. Prior to this,
many libraries simply provided export to PyArrow data structures, using the
<code class="docutils literal notranslate"><span class="pre">_import_from_c</span></code> and <code class="docutils literal notranslate"><span class="pre">_export_to_c</span></code> methods. However, this always required
PyArrow to be installed. In addition, those APIs could cause memory leaks if
handled improperly.</p>
<p>This interface allows any library to export Arrow data structures to other
libraries that understand the same protocol.</p>
<section id="goals">
<h3>Goals<a class="headerlink" href="#goals" title="Link to this heading">#</a></h3>
<ul class="simple">
<li><p>Standardize the <a class="reference external" href="https://docs.python.org/3/c-api/capsule.html">PyCapsule</a> objects that represent <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code>, <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code>,
<code class="docutils literal notranslate"><span class="pre">ArrowArrayStream</span></code>, <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code>.</p></li>
<li><p>Define standard methods that export Arrow data into such capsule objects,
so that any Python library wanting to accept Arrow data as input can call the
corresponding method instead of hardcoding support for specific Arrow
producers.</p></li>
</ul>
</section>
<section id="non-goals">
<h3>Non-goals<a class="headerlink" href="#non-goals" title="Link to this heading">#</a></h3>
<ul class="simple">
<li><p>Standardize what public APIs should be used for import. This is left up to
individual libraries.</p></li>
</ul>
</section>
</section>
<section id="pycapsule-standard">
<h2>PyCapsule Standard<a class="headerlink" href="#pycapsule-standard" title="Link to this heading">#</a></h2>
<p>When exporting Arrow data through Python, the C Data Interface / C Stream Interface
structures should be wrapped in capsules. Capsules avoid invalid access by
attaching a name to the pointer and avoid memory leaks by attaching a destructor.
Thus, they are much safer than passing pointers as integers.</p>
<p><a class="reference external" href="https://docs.python.org/3/c-api/capsule.html">PyCapsule</a> allows for a <code class="docutils literal notranslate"><span class="pre">name</span></code> to be associated with the capsule, allowing
consumers to verify that the capsule contains the expected kind of data. To make sure
Arrow structures are recognized, the following names must be used:</p>
<div class="pst-scrollable-table-container"><table class="table">
<colgroup>
<col style="width: 50.0%" />
<col style="width: 50.0%" />
</colgroup>
<thead>
<tr class="row-odd"><th class="head"><p>C Interface Type</p></th>
<th class="head"><p>PyCapsule Name</p></th>
</tr>
</thead>
<tbody>
<tr class="row-even"><td><p>ArrowSchema</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">arrow_schema</span></code></p></td>
</tr>
<tr class="row-odd"><td><p>ArrowArray</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">arrow_array</span></code></p></td>
</tr>
<tr class="row-even"><td><p>ArrowArrayStream</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">arrow_array_stream</span></code></p></td>
</tr>
<tr class="row-odd"><td><p>ArrowDeviceArray</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">arrow_device_array</span></code></p></td>
</tr>
<tr class="row-even"><td><p>ArrowDeviceArrayStream</p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">arrow_device_array_stream</span></code></p></td>
</tr>
</tbody>
</table>
</div>
<section id="lifetime-semantics">
<h3>Lifetime Semantics<a class="headerlink" href="#lifetime-semantics" title="Link to this heading">#</a></h3>
<p>The exported PyCapsules should have a destructor that calls the
<a class="reference internal" href="../CDataInterface.html#c-data-interface-released"><span class="std std-ref">release callback</span></a>
of the Arrow struct, if it is not already null. This prevents a memory leak in
case the capsule was never passed to another consumer.</p>
<p>If the capsule has been passed to a consumer, the consumer should have moved
the data and marked the release callback as null, so there isn’t a risk of
releasing data the consumer is using.
<a class="reference internal" href="../CDataInterface.html#c-data-interface-released"><span class="std std-ref">Read more in the C Data Interface specification</span></a>.</p>
<p>In case of a device struct, the above mentioned release callback is the
<code class="docutils literal notranslate"><span class="pre">release</span></code> member of the embedded <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> structure.
<a class="reference internal" href="../CDeviceDataInterface.html#c-device-data-interface-semantics"><span class="std std-ref">Read more in the C Device Interface specification</span></a>.</p>
<p>Just like in the C Data Interface, the PyCapsule objects defined here can only
be consumed once.</p>
<p>For an example of a PyCapsule with a destructor, see <a class="reference internal" href="#create-a-pycapsule">Create a PyCapsule</a>.</p>
</section>
</section>
<section id="export-protocol">
<h2>Export Protocol<a class="headerlink" href="#export-protocol" title="Link to this heading">#</a></h2>
<p>The interface consists of three separate protocols:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">ArrowSchemaExportable</span></code>, which defines the <code class="docutils literal notranslate"><span class="pre">__arrow_c_schema__</span></code> method.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ArrowArrayExportable</span></code>, which defines the <code class="docutils literal notranslate"><span class="pre">__arrow_c_array__</span></code> method.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ArrowStreamExportable</span></code>, which defines the <code class="docutils literal notranslate"><span class="pre">__arrow_c_stream__</span></code> method.</p></li>
</ul>
<p>Two additional protocols are defined for the Device interface:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayExportable</span></code>, which defines the <code class="docutils literal notranslate"><span class="pre">__arrow_c_device_array__</span></code> method.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ArrowDeviceStreamExportable</span></code>, which defines the <code class="docutils literal notranslate"><span class="pre">__arrow_c_device_stream__</span></code> method.</p></li>
</ul>
<section id="arrowschema-export">
<h3>ArrowSchema Export<a class="headerlink" href="#arrowschema-export" title="Link to this heading">#</a></h3>
<p>Schemas, fields, and data types can implement the method <code class="docutils literal notranslate"><span class="pre">__arrow_c_schema__</span></code>.</p>
<dl class="py method">
<dt class="sig sig-object py" id="arrow_c_schema__">
<span class="sig-name descname"><span class="pre">__arrow_c_schema__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#arrow_c_schema__" title="Link to this definition">#</a></dt>
<dd><p>Export the object as an ArrowSchema.</p>
<dl class="field-list simple">
<dt class="field-odd">Returns<span class="colon">:</span></dt>
<dd class="field-odd"><p>A PyCapsule containing a C ArrowSchema representation of the
object. The capsule must have a name of <code class="docutils literal notranslate"><span class="pre">&quot;arrow_schema&quot;</span></code>.</p>
</dd>
</dl>
</dd></dl>
</section>
<section id="arrowarray-export">
<h3>ArrowArray Export<a class="headerlink" href="#arrowarray-export" title="Link to this heading">#</a></h3>
<p>Arrays and record batches (contiguous tables) can implement the method
<code class="docutils literal notranslate"><span class="pre">__arrow_c_array__</span></code>.</p>
<dl class="py method">
<dt class="sig sig-object py" id="arrow_c_array__">
<span class="sig-name descname"><span class="pre">__arrow_c_array__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">requested_schema</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#arrow_c_array__" title="Link to this definition">#</a></dt>
<dd><p>Export the object as a pair of ArrowSchema and ArrowArray structures.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>requested_schema</strong> (<em>PyCapsule</em><em> or </em><em>None</em>) – A PyCapsule containing a C ArrowSchema representation
of a requested schema. Conversion to this schema is best-effort. See
<a class="reference internal" href="#schema-requests">Schema Requests</a>.</p>
</dd>
<dt class="field-even">Returns<span class="colon">:</span></dt>
<dd class="field-even"><p>A pair of PyCapsules containing a C ArrowSchema and ArrowArray,
respectively. The schema capsule should have the name <code class="docutils literal notranslate"><span class="pre">&quot;arrow_schema&quot;</span></code>
and the array capsule should have the name <code class="docutils literal notranslate"><span class="pre">&quot;arrow_array&quot;</span></code>.</p>
</dd>
</dl>
</dd></dl>
<p>Libraries supporting the Device interface can implement a <code class="docutils literal notranslate"><span class="pre">__arrow_c_device_array__</span></code>
method on those objects, which works the same as <code class="docutils literal notranslate"><span class="pre">__arrow_c_array__</span></code> except
for returning an ArrowDeviceArray structure instead of an ArrowArray structure:</p>
<dl class="py method">
<dt class="sig sig-object py" id="arrow_c_device_array__">
<span class="sig-name descname"><span class="pre">__arrow_c_device_array__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">requested_schema</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#arrow_c_device_array__" title="Link to this definition">#</a></dt>
<dd><p>Export the object as a pair of ArrowSchema and ArrowDeviceArray structures.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>requested_schema</strong> (<em>PyCapsule</em><em> or </em><em>None</em>) – A PyCapsule containing a C ArrowSchema representation
of a requested schema. Conversion to this schema is best-effort. See
<a class="reference internal" href="#schema-requests">Schema Requests</a>.</p></li>
<li><p><strong>kwargs</strong> – Additional keyword arguments should only be accepted if they have
a default value of <code class="docutils literal notranslate"><span class="pre">None</span></code>, to allow for future addition of new keywords.
See <a class="reference internal" href="#arrow-pycapsule-interface-device-support"><span class="std std-ref">Device Support</span></a> for more details.</p></li>
</ul>
</dd>
<dt class="field-even">Returns<span class="colon">:</span></dt>
<dd class="field-even"><p>A pair of PyCapsules containing a C ArrowSchema and ArrowDeviceArray,
respectively. The schema capsule should have the name <code class="docutils literal notranslate"><span class="pre">&quot;arrow_schema&quot;</span></code>
and the array capsule should have the name <code class="docutils literal notranslate"><span class="pre">&quot;arrow_device_array&quot;</span></code>.</p>
</dd>
</dl>
</dd></dl>
</section>
<section id="arrowstream-export">
<h3>ArrowStream Export<a class="headerlink" href="#arrowstream-export" title="Link to this heading">#</a></h3>
<p>Tables / DataFrames and streams can implement the method <code class="docutils literal notranslate"><span class="pre">__arrow_c_stream__</span></code>.</p>
<dl class="py method">
<dt class="sig sig-object py" id="arrow_c_stream__">
<span class="sig-name descname"><span class="pre">__arrow_c_stream__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">requested_schema</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#arrow_c_stream__" title="Link to this definition">#</a></dt>
<dd><p>Export the object as an ArrowArrayStream.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><p><strong>requested_schema</strong> (<em>PyCapsule</em><em> or </em><em>None</em>) – A PyCapsule containing a C ArrowSchema representation
of a requested schema. Conversion to this schema is best-effort. See
<a class="reference internal" href="#schema-requests">Schema Requests</a>.</p>
</dd>
<dt class="field-even">Returns<span class="colon">:</span></dt>
<dd class="field-even"><p>A PyCapsule containing a C ArrowArrayStream representation of the
object. The capsule must have a name of <code class="docutils literal notranslate"><span class="pre">&quot;arrow_array_stream&quot;</span></code>.</p>
</dd>
</dl>
</dd></dl>
<p>Libraries supporting the Device interface can implement a <code class="docutils literal notranslate"><span class="pre">__arrow_c_device_stream__</span></code>
method on those objects, which works the same as <code class="docutils literal notranslate"><span class="pre">__arrow_c_stream__</span></code> except
for returning an ArrowDeviceArrayStream structure instead of an ArrowArrayStream
structure:</p>
<dl class="py method">
<dt class="sig sig-object py" id="arrow_c_device_stream__">
<span class="sig-name descname"><span class="pre">__arrow_c_device_stream__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="n"><span class="pre">self</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">requested_schema</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#arrow_c_device_stream__" title="Link to this definition">#</a></dt>
<dd><p>Export the object as an ArrowDeviceArrayStream.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters<span class="colon">:</span></dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>requested_schema</strong> (<em>PyCapsule</em><em> or </em><em>None</em>) – A PyCapsule containing a C ArrowSchema representation
of a requested schema. Conversion to this schema is best-effort. See
<a class="reference internal" href="#schema-requests">Schema Requests</a>.</p></li>
<li><p><strong>kwargs</strong> – Additional keyword arguments should only be accepted if they have
a default value of <code class="docutils literal notranslate"><span class="pre">None</span></code>, to allow for future addition of new keywords.
See <a class="reference internal" href="#arrow-pycapsule-interface-device-support"><span class="std std-ref">Device Support</span></a> for more details.</p></li>
</ul>
</dd>
<dt class="field-even">Returns<span class="colon">:</span></dt>
<dd class="field-even"><p>A PyCapsule containing a C ArrowDeviceArrayStream representation of the
object. The capsule must have a name of <code class="docutils literal notranslate"><span class="pre">&quot;arrow_device_array_stream&quot;</span></code>.</p>
</dd>
</dl>
</dd></dl>
</section>
<section id="schema-requests">
<h3>Schema Requests<a class="headerlink" href="#schema-requests" title="Link to this heading">#</a></h3>
<p>In some cases, there might be multiple possible Arrow representations of the
same data. For example, a library might have a single integer type, but Arrow
has multiple integer types with different sizes and sign. As another example,
Arrow has several possible encodings for an array of strings: 32-bit offsets,
64-bit offsets, string view, and dictionary-encoded. A sequence of strings could
export to any one of these Arrow representations.</p>
<p>In order to allow the caller to request a specific representation, the
<a class="reference internal" href="#arrow_c_array__" title="__arrow_c_array__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_array__()</span></code></a> and <a class="reference internal" href="#arrow_c_stream__" title="__arrow_c_stream__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_stream__()</span></code></a> methods take an optional
<code class="docutils literal notranslate"><span class="pre">requested_schema</span></code> parameter. This parameter is a PyCapsule containing an
<code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code>.</p>
<p>The callee should attempt to provide the data in the requested schema. However,
if the callee cannot provide the data in the requested schema, they may return
with the same schema as if <code class="docutils literal notranslate"><span class="pre">None</span></code> were passed to <code class="docutils literal notranslate"><span class="pre">requested_schema</span></code>.</p>
<p>If the caller requests a schema that is not compatible with the data,
say requesting a schema with a different number of fields, the callee should
raise an exception. The requested schema mechanism is only meant to negotiate
between different representations of the same data and not to allow arbitrary
schema transformations.</p>
</section>
<section id="device-support">
<span id="arrow-pycapsule-interface-device-support"></span><h3>Device Support<a class="headerlink" href="#device-support" title="Link to this heading">#</a></h3>
<p>The PyCapsule interface has cross hardware support through using the
<a class="reference internal" href="../CDeviceDataInterface.html#c-device-data-interface"><span class="std std-ref">C device interface</span></a>. This means it is possible
to exchange data on non-CPU devices (e.g. CUDA GPUs) and to inspect on what
device the exchanged data lives.</p>
<p>For exchanging the data structures, this interface has two sets of protocol
methods: the standard CPU-only versions (<a class="reference internal" href="#arrow_c_array__" title="__arrow_c_array__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_array__()</span></code></a> and
<a class="reference internal" href="#arrow_c_stream__" title="__arrow_c_stream__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_stream__()</span></code></a>) and the equivalent device-aware versions
(<a class="reference internal" href="#arrow_c_device_array__" title="__arrow_c_device_array__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_device_array__()</span></code></a>, and <a class="reference internal" href="#arrow_c_device_stream__" title="__arrow_c_device_stream__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_device_stream__()</span></code></a>).</p>
<p>For CPU-only producers, it is allowed to either implement only the standard
CPU-only protocol methods, or either implement both the CPU-only and device-aware
methods. The absence of the device version methods implies CPU-only data. For
CPU-only consumers, it is encouraged to be able to consume both versions of the
protocol.</p>
<p>For a device-aware producer whose data structures can only reside in
non-CPU memory, it is recommended to only implement the device version of the
protocol (e.g. only add <code class="docutils literal notranslate"><span class="pre">__arrow_c_device_array__</span></code>, and not add <code class="docutils literal notranslate"><span class="pre">__arrow_c_array__</span></code>).
Producers that have data structures that can live both on CPU or non-CPU devices
can implement both versions of the protocol, but the CPU-only versions
(<a class="reference internal" href="#arrow_c_array__" title="__arrow_c_array__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_array__()</span></code></a> and <a class="reference internal" href="#arrow_c_stream__" title="__arrow_c_stream__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_stream__()</span></code></a>) should be guaranteed
to contain valid pointers for CPU memory (thus, when trying to export non-CPU data,
either raise an error or make a copy to CPU memory).</p>
<p>Producing the <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArray</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowDeviceArrayStream</span></code> structures
is expected to not involve any cross-device copying of data.</p>
<p>The device-aware methods (<a class="reference internal" href="#arrow_c_device_array__" title="__arrow_c_device_array__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_device_array__()</span></code></a>, and <a class="reference internal" href="#arrow_c_device_stream__" title="__arrow_c_device_stream__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_device_stream__()</span></code></a>)
should accept additional keyword arguments (<code class="docutils literal notranslate"><span class="pre">**kwargs</span></code>), if they have a
default value of <code class="docutils literal notranslate"><span class="pre">None</span></code>. This allows for future addition of new optional
keywords, where the default value for such a new keyword will always be <code class="docutils literal notranslate"><span class="pre">None</span></code>.
The implementor is responsible for raising a <code class="docutils literal notranslate"><span class="pre">NotImplementedError</span></code> for any
additional keyword being passed by the user which is not recognised. For
example:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">def</span><span class="w"> </span><span class="nf">__arrow_c_device_array__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">requested_schema</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="n">non_default_kwargs</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">name</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">()</span> <span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
<span class="p">]</span>
<span class="k">if</span> <span class="n">non_default_kwargs</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span>
<span class="sa">f</span><span class="s2">&quot;Received unsupported keyword argument(s): </span><span class="si">{</span><span class="n">non_default_kwargs</span><span class="si">}</span><span class="s2">&quot;</span>
<span class="p">)</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
<section id="protocol-typehints">
<h3>Protocol Typehints<a class="headerlink" href="#protocol-typehints" title="Link to this heading">#</a></h3>
<p>The following typehints can be copied into your library to annotate that a
function accepts an object implementing one of these protocols.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span><span class="w"> </span><span class="nn">typing</span><span class="w"> </span><span class="kn">import</span> <span class="n">Tuple</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ArrowSchemaExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">__arrow_c_schema__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">object</span><span class="p">:</span> <span class="o">...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ArrowArrayExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">__arrow_c_array__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">requested_schema</span><span class="p">:</span> <span class="nb">object</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">object</span><span class="p">,</span> <span class="nb">object</span><span class="p">]:</span>
<span class="o">...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ArrowStreamExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">__arrow_c_stream__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">requested_schema</span><span class="p">:</span> <span class="nb">object</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">object</span><span class="p">:</span>
<span class="o">...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ArrowDeviceArrayExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">__arrow_c_device_array__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">requested_schema</span><span class="p">:</span> <span class="nb">object</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Tuple</span><span class="p">[</span><span class="nb">object</span><span class="p">,</span> <span class="nb">object</span><span class="p">]:</span>
<span class="o">...</span>
<span class="k">class</span><span class="w"> </span><span class="nc">ArrowDeviceStreamExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</span><span class="w"> </span><span class="nf">__arrow_c_device_stream__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">requested_schema</span><span class="p">:</span> <span class="nb">object</span> <span class="o">|</span> <span class="kc">None</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span>
<span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">object</span><span class="p">:</span>
<span class="o">...</span>
</pre></div>
</div>
</section>
</section>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Link to this heading">#</a></h2>
<section id="create-a-pycapsule">
<h3>Create a PyCapsule<a class="headerlink" href="#create-a-pycapsule" title="Link to this heading">#</a></h3>
<p>To create a PyCapsule, use the <a class="reference external" href="https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_New">PyCapsule_New</a>
function. The function must be passed a destructor function that will be called
to release the data the capsule points to. It must first call the release
callback if it is not null, then free the struct.</p>
<p>Below is the code to create a PyCapsule for an <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code>. The code for
<code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArrayStream</span></code> is similar.</p>
<div class="sd-tab-set docutils">
<input checked="checked" id="sd-tab-item-0" name="sd-tab-set-0" type="radio">
<label class="sd-tab-label" for="sd-tab-item-0">
C</label><div class="sd-tab-content docutils">
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;Python.h&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">ReleaseArrowSchemaPyCapsule</span><span class="p">(</span><span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="n">capsule</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="o">*</span><span class="w"> </span><span class="n">schema</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="o">*</span><span class="p">)</span><span class="n">PyCapsule_GetPointer</span><span class="p">(</span><span class="n">capsule</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;arrow_schema&quot;</span><span class="p">);</span>
<span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">schema</span><span class="o">-&gt;</span><span class="n">release</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">NULL</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="n">schema</span><span class="o">-&gt;</span><span class="n">release</span><span class="p">(</span><span class="n">schema</span><span class="p">);</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">free</span><span class="p">(</span><span class="n">schema</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="nf">ExportArrowSchemaPyCapsule</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="o">*</span><span class="w"> </span><span class="n">schema</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="p">));</span>
<span class="w"> </span><span class="c1">// Fill in ArrowSchema fields</span>
<span class="w"> </span><span class="c1">// ...</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">PyCapsule_New</span><span class="p">(</span><span class="n">schema</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;arrow_schema&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">ReleaseArrowSchemaPyCapsule</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<input id="sd-tab-item-1" name="sd-tab-set-0" type="radio">
<label class="sd-tab-label" for="sd-tab-item-1">
Cython</label><div class="sd-tab-content docutils">
<div class="highlight-cython notranslate"><div class="highlight"><pre><span></span><span class="k">cimport</span><span class="w"> </span><span class="nn">cpython</span>
<span class="k">from</span><span class="w"> </span><span class="nn">libc.stdlib</span><span class="w"> </span><span class="k">cimport</span> <span class="n">malloc</span><span class="p">,</span> <span class="n">free</span>
<span class="k">cdef</span><span class="w"> </span><span class="kt">void</span> <span class="nf">release_arrow_schema_py_capsule</span><span class="p">(</span><span class="nb">object</span> <span class="n">schema_capsule</span><span class="p">):</span>
<span class="k">cdef</span><span class="w"> </span><span class="kt">ArrowSchema</span>* <span class="nf">schema</span><span class="w"> </span><span class="o">=</span> <span class="o">&lt;</span><span class="n">ArrowSchema</span><span class="o">*&gt;</span><span class="n">cpython</span><span class="o">.</span><span class="n">PyCapsule_GetPointer</span><span class="p">(</span>
<span class="n">schema_capsule</span><span class="p">,</span> <span class="s">&#39;arrow_schema&#39;</span>
<span class="p">)</span>
<span class="k">if</span> <span class="n">schema</span><span class="o">.</span><span class="n">release</span> <span class="o">!=</span> <span class="bp">NULL</span><span class="p">:</span>
<span class="n">schema</span><span class="o">.</span><span class="n">release</span><span class="p">(</span><span class="n">schema</span><span class="p">)</span>
<span class="n">free</span><span class="p">(</span><span class="n">schema</span><span class="p">)</span>
<span class="k">cdef</span><span class="w"> </span><span class="kt">object</span> <span class="nf">export_arrow_schema_py_capsule</span><span class="p">():</span>
<span class="k">cdef</span><span class="w"> </span><span class="kt">ArrowSchema</span>* <span class="nf">schema</span><span class="w"> </span><span class="o">=</span> <span class="o">&lt;</span><span class="n">ArrowSchema</span><span class="o">*&gt;</span><span class="n">malloc</span><span class="p">(</span><span class="n">sizeof</span><span class="p">(</span><span class="n">ArrowSchema</span><span class="p">))</span>
<span class="c"># It&#39;s recommended to immediately wrap the struct in a capsule, so</span>
<span class="c"># if subsequent lines raise an exception memory will not be leaked.</span>
<span class="n">schema</span><span class="o">.</span><span class="n">release</span> <span class="o">=</span> <span class="bp">NULL</span>
<span class="n">capsule</span> <span class="o">=</span> <span class="n">cpython</span><span class="o">.</span><span class="n">PyCapsule_New</span><span class="p">(</span>
<span class="o">&lt;</span><span class="n">void</span><span class="o">*&gt;</span><span class="n">schema</span><span class="p">,</span> <span class="s">&#39;arrow_schema&#39;</span><span class="p">,</span> <span class="n">release_arrow_schema_py_capsule</span>
<span class="p">)</span>
<span class="c"># Fill in ArrowSchema fields:</span>
<span class="c"># schema.format = ...</span>
<span class="c"># ...</span>
<span class="k">return</span> <span class="n">capsule</span>
</pre></div>
</div>
</div>
</div>
</section>
<section id="consume-a-pycapsule">
<h3>Consume a PyCapsule<a class="headerlink" href="#consume-a-pycapsule" title="Link to this heading">#</a></h3>
<p>To consume a PyCapsule, use the <a class="reference external" href="https://docs.python.org/3/c-api/capsule.html#c.PyCapsule_GetPointer">PyCapsule_GetPointer</a> function
to get the pointer to the underlying struct. Import the struct using your
system’s Arrow C Data Interface import function. Only after that should the
capsule be freed.</p>
<p>The below example shows how to consume a PyCapsule for an <code class="docutils literal notranslate"><span class="pre">ArrowSchema</span></code>. The
code for <code class="docutils literal notranslate"><span class="pre">ArrowArray</span></code> and <code class="docutils literal notranslate"><span class="pre">ArrowArrayStream</span></code> is similar.</p>
<div class="sd-tab-set docutils">
<input checked="checked" id="sd-tab-item-2" name="sd-tab-set-1" type="radio">
<label class="sd-tab-label" for="sd-tab-item-2">
C</label><div class="sd-tab-content docutils">
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&lt;Python.h&gt;</span>
<span class="c1">// If the capsule is not an ArrowSchema, will return NULL and set an exception.</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ArrowSchema</span><span class="o">*</span><span class="w"> </span><span class="n">GetArrowSchemaPyCapsule</span><span class="p">(</span><span class="n">PyObject</span><span class="o">*</span><span class="w"> </span><span class="n">capsule</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">PyCapsule_GetPointer</span><span class="p">(</span><span class="n">capsule</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;arrow_schema&quot;</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
</div>
<input id="sd-tab-item-3" name="sd-tab-set-1" type="radio">
<label class="sd-tab-label" for="sd-tab-item-3">
Cython</label><div class="sd-tab-content docutils">
<div class="highlight-cython notranslate"><div class="highlight"><pre><span></span><span class="k">cimport</span><span class="w"> </span><span class="nn">cpython</span>
<span class="k">cdef</span><span class="w"> </span><span class="kt">ArrowSchema</span>* <span class="nf">get_arrow_schema_py_capsule</span><span class="p">(</span><span class="nb">object</span> <span class="n">capsule</span><span class="p">)</span> <span class="k">except</span> <span class="bp">NULL</span><span class="p">:</span>
<span class="k">return</span> <span class="o">&lt;</span><span class="n">ArrowSchema</span><span class="o">*&gt;</span><span class="n">cpython</span><span class="o">.</span><span class="n">PyCapsule_GetPointer</span><span class="p">(</span><span class="n">capsule</span><span class="p">,</span> <span class="s">&#39;arrow_schema&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</section>
<section id="backwards-compatibility-with-pyarrow">
<h3>Backwards Compatibility with PyArrow<a class="headerlink" href="#backwards-compatibility-with-pyarrow" title="Link to this heading">#</a></h3>
<p>When interacting with PyArrow, the PyCapsule interface should be preferred over
the <code class="docutils literal notranslate"><span class="pre">_export_to_c</span></code> and <code class="docutils literal notranslate"><span class="pre">_import_from_c</span></code> methods. However, many libraries will
want to support a range of PyArrow versions. This can be done via Duck typing.</p>
<p>For example, if your library had an import method such as:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># OLD METHOD</span>
<span class="k">def</span><span class="w"> </span><span class="nf">from_arrow</span><span class="p">(</span><span class="n">arr</span><span class="p">:</span> <span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="p">)</span>
<span class="n">array_import_ptr</span> <span class="o">=</span> <span class="n">make_array_import_ptr</span><span class="p">()</span>
<span class="n">schema_import_ptr</span> <span class="o">=</span> <span class="n">make_schema_import_ptr</span><span class="p">()</span>
<span class="n">arr</span><span class="o">.</span><span class="n">_export_to_c</span><span class="p">(</span><span class="n">array_import_ptr</span><span class="p">,</span> <span class="n">schema_import_ptr</span><span class="p">)</span>
<span class="k">return</span> <span class="n">import_c_data</span><span class="p">(</span><span class="n">array_import_ptr</span><span class="p">,</span> <span class="n">schema_import_ptr</span><span class="p">)</span>
</pre></div>
</div>
<p>You can rewrite this method to support both PyArrow and other libraries that
implement the PyCapsule interface:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># NEW METHOD</span>
<span class="k">def</span><span class="w"> </span><span class="nf">from_arrow</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>
<span class="c1"># Newer versions of PyArrow as well as other libraries with Arrow data</span>
<span class="c1"># implement this method, so prefer it over _export_to_c.</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="s2">&quot;__arrow_c_array__&quot;</span><span class="p">):</span>
<span class="n">schema_ptr</span><span class="p">,</span> <span class="n">array_ptr</span> <span class="o">=</span> <span class="n">arr</span><span class="o">.</span><span class="n">__arrow_c_array__</span><span class="p">()</span>
<span class="k">return</span> <span class="n">import_c_capsule_data</span><span class="p">(</span><span class="n">schema_ptr</span><span class="p">,</span> <span class="n">array_ptr</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="p">):</span>
<span class="c1"># Deprecated method, used for older versions of PyArrow</span>
<span class="n">array_import_ptr</span> <span class="o">=</span> <span class="n">make_array_import_ptr</span><span class="p">()</span>
<span class="n">schema_import_ptr</span> <span class="o">=</span> <span class="n">make_schema_import_ptr</span><span class="p">()</span>
<span class="n">arr</span><span class="o">.</span><span class="n">_export_to_c</span><span class="p">(</span><span class="n">array_import_ptr</span><span class="p">,</span> <span class="n">schema_import_ptr</span><span class="p">)</span>
<span class="k">return</span> <span class="n">import_c_data</span><span class="p">(</span><span class="n">array_import_ptr</span><span class="p">,</span> <span class="n">schema_import_ptr</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Cannot import </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="si">}</span><span class="s2"> as Arrow array data.&quot;</span><span class="p">)</span>
</pre></div>
</div>
<p>You may also wish to accept objects implementing the protocol in your
constructors. For example, in PyArrow, the <code class="xref py py-func docutils literal notranslate"><span class="pre">array()</span></code> and <code class="xref py py-func docutils literal notranslate"><span class="pre">record_batch()</span></code>
constructors accept any object that implements the <a class="reference internal" href="#arrow_c_array__" title="__arrow_c_array__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_array__()</span></code></a> method
protocol. Similarly, the PyArrow’s <code class="xref py py-func docutils literal notranslate"><span class="pre">schema()</span></code> constructor accepts any object
that implements the <a class="reference internal" href="#arrow_c_schema__" title="__arrow_c_schema__"><code class="xref py py-meth docutils literal notranslate"><span class="pre">__arrow_c_schema__()</span></code></a> method.</p>
<p>Now if your library has an export to PyArrow function, such as:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># OLD METHOD</span>
<span class="k">def</span><span class="w"> </span><span class="nf">to_arrow</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="p">:</span>
<span class="n">array_export_ptr</span> <span class="o">=</span> <span class="n">make_array_export_ptr</span><span class="p">()</span>
<span class="n">schema_export_ptr</span> <span class="o">=</span> <span class="n">make_schema_export_ptr</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">export_c_data</span><span class="p">(</span><span class="n">array_export_ptr</span><span class="p">,</span> <span class="n">schema_export_ptr</span><span class="p">)</span>
<span class="k">return</span> <span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="o">.</span><span class="n">_import_from_c</span><span class="p">(</span><span class="n">array_export_ptr</span><span class="p">,</span> <span class="n">schema_export_ptr</span><span class="p">)</span>
</pre></div>
</div>
<p>You can rewrite this function to use the PyCapsule interface by passing your
object to the <code class="xref py py-func docutils literal notranslate"><span class="pre">array()</span></code> constructor, which accepts any object that
implements the protocol. An easy way to check if the PyArrow version is new
enough to support this is to check whether <code class="docutils literal notranslate"><span class="pre">pa.Array</span></code> has the
<code class="docutils literal notranslate"><span class="pre">__arrow_c_array__</span></code> method.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span><span class="w"> </span><span class="nn">warnings</span>
<span class="c1"># NEW METHOD</span>
<span class="k">def</span><span class="w"> </span><span class="nf">to_arrow</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="p">:</span>
<span class="c1"># PyArrow added support for constructing arrays from objects implementing</span>
<span class="c1"># __arrow_c_array__ in the same version it added the method for it&#39;s own</span>
<span class="c1"># arrays. So we can use hasattr to check if the method is available as</span>
<span class="c1"># a proxy for checking the PyArrow version.</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="p">,</span> <span class="s2">&quot;__arrow_c_array__&quot;</span><span class="p">):</span>
<span class="k">return</span> <span class="n">pa</span><span class="o">.</span><span class="n">array</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">array_export_ptr</span> <span class="o">=</span> <span class="n">make_array_export_ptr</span><span class="p">()</span>
<span class="n">schema_export_ptr</span> <span class="o">=</span> <span class="n">make_schema_export_ptr</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">export_c_data</span><span class="p">(</span><span class="n">array_export_ptr</span><span class="p">,</span> <span class="n">schema_export_ptr</span><span class="p">)</span>
<span class="k">return</span> <span class="n">pa</span><span class="o">.</span><span class="n">Array</span><span class="o">.</span><span class="n">_import_from_c</span><span class="p">(</span><span class="n">array_export_ptr</span><span class="p">,</span> <span class="n">schema_export_ptr</span><span class="p">)</span>
</pre></div>
</div>
</section>
</section>
<section id="comparison-with-other-protocols">
<h2>Comparison with Other Protocols<a class="headerlink" href="#comparison-with-other-protocols" title="Link to this heading">#</a></h2>
<section id="comparison-to-dataframe-interchange-protocol">
<h3>Comparison to DataFrame Interchange Protocol<a class="headerlink" href="#comparison-to-dataframe-interchange-protocol" title="Link to this heading">#</a></h3>
<p><a class="reference external" href="https://data-apis.org/dataframe-protocol/latest/">The DataFrame Interchange Protocol</a>
is another protocol in Python that allows for the sharing of data between libraries.
This protocol is complementary to the DataFrame Interchange Protocol. Many of
the objects that implement this protocol will also implement the DataFrame
Interchange Protocol.</p>
<p>This protocol is specific to Arrow-based data structures, while the DataFrame
Interchange Protocol allows non-Arrow data frames and arrays to be shared as well.
Because of this, these PyCapsules can support Arrow-specific features such as
nested columns.</p>
<p>This protocol is also much more minimal than the DataFrame Interchange Protocol.
It just handles data export, rather than defining accessors for details like
number of rows or columns.</p>
<p>In summary, if you are implementing this protocol, you should also consider
implementing the DataFrame Interchange Protocol.</p>
</section>
<section id="comparison-to-arrow-array-protocol">
<h3>Comparison to <code class="docutils literal notranslate"><span class="pre">__arrow_array__</span></code> protocol<a class="headerlink" href="#comparison-to-arrow-array-protocol" title="Link to this heading">#</a></h3>
<p>The <a class="reference internal" href="../../python/extending_types.html#arrow-array-protocol"><span class="std std-ref">Controlling conversion to pyarrow.Array with the __arrow_array__ protocol</span></a> protocol is a dunder method that
defines how PyArrow should import an object as an Arrow array. Unlike this
protocol, it is specific to PyArrow and isn’t used by other libraries. It is
also limited to arrays and does not support schemas, tabular structures, or streams.</p>
</section>
</section>
</section>
</article>
<footer class="prev-next-footer d-print-none">
<div class="prev-next-area">
<a class="left-prev"
href="../CDataInterface.html"
title="previous page">
<i class="fa-solid fa-angle-left"></i>
<div class="prev-next-info">
<p class="prev-next-subtitle">previous</p>
<p class="prev-next-title">The Arrow C data interface</p>
</div>
</a>
<a class="right-next"
href="../CStreamInterface.html"
title="next page">
<div class="prev-next-info">
<p class="prev-next-subtitle">next</p>
<p class="prev-next-title">The Arrow C stream interface</p>
</div>
<i class="fa-solid fa-angle-right"></i>
</a>
</div>
</footer>
</div>
<dialog id="pst-secondary-sidebar-modal"></dialog>
<div id="pst-secondary-sidebar" class="bd-sidebar-secondary bd-toc"><div class="sidebar-secondary-items sidebar-secondary__inner">
<div class="sidebar-secondary-item">
<div
id="pst-page-navigation-heading-2"
class="page-toc tocsection onthispage">
<i class="fa-solid fa-list"></i> On this page
</div>
<nav class="bd-toc-nav page-toc" aria-labelledby="pst-page-navigation-heading-2">
<ul class="visible nav section-nav flex-column">
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#rationale">Rationale</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#goals">Goals</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#non-goals">Non-goals</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#pycapsule-standard">PyCapsule Standard</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#lifetime-semantics">Lifetime Semantics</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#export-protocol">Export Protocol</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#arrowschema-export">ArrowSchema Export</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow_c_schema__"><code class="docutils literal notranslate"><span class="pre">__arrow_c_schema__()</span></code></a></li>
</ul>
</li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#arrowarray-export">ArrowArray Export</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow_c_array__"><code class="docutils literal notranslate"><span class="pre">__arrow_c_array__()</span></code></a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow_c_device_array__"><code class="docutils literal notranslate"><span class="pre">__arrow_c_device_array__()</span></code></a></li>
</ul>
</li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#arrowstream-export">ArrowStream Export</a><ul class="nav section-nav flex-column">
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow_c_stream__"><code class="docutils literal notranslate"><span class="pre">__arrow_c_stream__()</span></code></a></li>
<li class="toc-h4 nav-item toc-entry"><a class="reference internal nav-link" href="#arrow_c_device_stream__"><code class="docutils literal notranslate"><span class="pre">__arrow_c_device_stream__()</span></code></a></li>
</ul>
</li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#schema-requests">Schema Requests</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#device-support">Device Support</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#protocol-typehints">Protocol Typehints</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#examples">Examples</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#create-a-pycapsule">Create a PyCapsule</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#consume-a-pycapsule">Consume a PyCapsule</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#backwards-compatibility-with-pyarrow">Backwards Compatibility with PyArrow</a></li>
</ul>
</li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#comparison-with-other-protocols">Comparison with Other Protocols</a><ul class="visible nav section-nav flex-column">
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#comparison-to-dataframe-interchange-protocol">Comparison to DataFrame Interchange Protocol</a></li>
<li class="toc-h3 nav-item toc-entry"><a class="reference internal nav-link" href="#comparison-to-arrow-array-protocol">Comparison to <code class="docutils literal notranslate"><span class="pre">__arrow_array__</span></code> protocol</a></li>
</ul>
</li>
</ul>
</nav></div>
<div class="sidebar-secondary-item">
<div class="tocsection editthispage">
<a href="https://github.com/apache/arrow/edit/main/docs/source/format/CDataInterface/PyCapsuleInterface.rst">
<i class="fa-solid fa-pencil"></i>
Edit on GitHub
</a>
</div>
</div>
</div></div>
</div>
<footer class="bd-footer-content">
</footer>
</main>
</div>
</div>
<!-- Scripts loaded after <body> so the DOM is not blocked -->
<script defer src="../../_static/scripts/bootstrap.js?digest=8878045cc6db502f8baf"></script>
<script defer src="../../_static/scripts/pydata-sphinx-theme.js?digest=8878045cc6db502f8baf"></script>
<footer class="bd-footer">
<div class="bd-footer__inner bd-page-width">
<div class="footer-items__start">
<div class="footer-item">
<p class="copyright">
© Copyright 2016-2025 Apache Software Foundation.
Apache Arrow, Arrow, Apache, the Apache logo, and the Apache Arrow project logo are either registered trademarks or trademarks of The Apache Software Foundation in the United States and other countries.
<br/>
</p>
</div>
<div class="footer-item">
<p class="sphinx-version">
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
<br/>
</p>
</div>
</div>
<div class="footer-items__end">
<div class="footer-item">
<p class="theme-version">
<!-- # L10n: Setting the PST URL as an argument as this does not need to be localized -->
Built with the <a href="https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html">PyData Sphinx Theme</a> 0.16.1.
</p></div>
</div>
</div>
</footer>
</body>
</html>