blob: 5d41484fab28088b6b53f631d69c0375f31223c1 [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="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
<title>The Arrow PyCapsule Interface &#8212; Apache Arrow v17.0.0.dev52</title>
<script data-cfasync="false">
document.documentElement.dataset.mode = localStorage.getItem("mode") || "";
document.documentElement.dataset.theme = localStorage.getItem("theme") || "light";
</script>
<!-- Loaded before other Sphinx assets -->
<link href="../../_static/styles/theme.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../../_static/styles/bootstrap.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../../_static/styles/pydata-sphinx-theme.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link href="../../_static/vendor/fontawesome/6.5.1/css/all.min.css?digest=8d27b9dea8ad943066ae" rel="stylesheet" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../../_static/vendor/fontawesome/6.5.1/webfonts/fa-solid-900.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../../_static/vendor/fontawesome/6.5.1/webfonts/fa-brands-400.woff2" />
<link rel="preload" as="font" type="font/woff2" crossorigin href="../../_static/vendor/fontawesome/6.5.1/webfonts/fa-regular-400.woff2" />
<link rel="stylesheet" type="text/css" href="../../_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="../../_static/copybutton.css" />
<link rel="stylesheet" type="text/css" href="../../_static/design-style.1e8bd061cd6da7fc9cf755528e8ffc24.min.css" />
<link rel="stylesheet" type="text/css" href="../../_static/theme_overrides.css" />
<!-- Pre-loaded scripts that we'll load fully later -->
<link rel="preload" as="script" href="../../_static/scripts/bootstrap.js?digest=8d27b9dea8ad943066ae" />
<link rel="preload" as="script" href="../../_static/scripts/pydata-sphinx-theme.js?digest=8d27b9dea8ad943066ae" />
<script src="../../_static/vendor/fontawesome/6.5.1/js/all.min.js?digest=8d27b9dea8ad943066ae"></script>
<script data-url_root="../../" id="documentation_options" src="../../_static/documentation_options.js"></script>
<script src="../../_static/doctools.js"></script>
<script src="../../_static/sphinx_highlight.js"></script>
<script src="../../_static/clipboard.min.js"></script>
<script src="../../_static/copybutton.js"></script>
<script src="../../_static/design-tabs.js"></script>
<script>DOCUMENTATION_OPTIONS.pagename = 'format/CDataInterface/PyCapsuleInterface';</script>
<script>
DOCUMENTATION_OPTIONS.theme_version = '0.15.2';
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"/>
<!-- 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="">
<a id="pst-skip-link" class="skip-link" href="#main-content">Skip to main content</a>
<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>
<input type="checkbox"
class="sidebar-toggle"
name="__primary"
id="__primary"/>
<label class="overlay overlay-primary" for="__primary"></label>
<input type="checkbox"
class="sidebar-toggle"
name="__secondary"
id="__secondary"/>
<label class="overlay overlay-secondary" for="__secondary"></label>
<div class="search-button__wrapper">
<div class="search-button__overlay"></div>
<div class="search-button__search-container">
<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"
id="search-input"
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></div>
</div>
<header class="bd-header navbar navbar-expand-lg bd-navbar">
<div class="bd-header__inner bd-page-width">
<label class="sidebar-toggle primary-toggle" for="__primary">
<span class="fa-solid fa-bars"></span>
</label>
<div class="col-lg-3 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 v17.0.0.dev52 - Home"/>
<script>document.write(`<img src="../../_static/arrow-dark.png" class="logo__image only-dark" alt="Apache Arrow v17.0.0.dev52 - Home"/>`);</script>
</a></div>
</div>
<div class="col-lg-9 navbar-header-items">
<div class="me-auto navbar-header-items__center">
<div class="navbar-item">
<nav class="navbar-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 dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-nav-more-links">
Implementations
</button>
<ul id="pst-nav-more-links" class="dropdown-menu">
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../c_glib/index.html">
C/GLib
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../cpp/index.html">
C++
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/csharp/README.md">
C#
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://pkg.go.dev/github.com/apache/arrow/go/v17">
Go
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../java/index.html">
Java
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../js/index.html">
JavaScript
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/julia/">
Julia
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/matlab/README.md">
MATLAB
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/nanoarrow/">
nanoarrow
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../python/index.html">
Python
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../r/index.html">
R
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/ruby/README.md">
Ruby
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://docs.rs/crate/arrow/">
Rust
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../status.html">
Implementation Status
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/cpp/">
C++ cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/java/">
Java cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/py/">
Python cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/r/">
R cookbook
</a>
</li>
</ul>
</li>
</ul>
</nav></div>
</div>
<div class="navbar-header-items__end">
<div class="navbar-item navbar-persistent--container">
<script>
document.write(`
<button class="btn navbar-btn search-button-field search-button__button" 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>
`);
</script>
</div>
<div class="navbar-item">
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="pst-version-switcher-button-2"
type="button"
class="version-switcher__button btn btn-sm navbar-btn 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>
`);
</script></div>
<div class="navbar-item">
<script>
document.write(`
<button class="btn btn-sm navbar-btn theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="theme-switch nav-link" data-mode="light"><i class="fa-solid fa-sun fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="dark"><i class="fa-solid fa-moon fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg"></i></span>
</button>
`);
</script></div>
<div class="navbar-item"><ul class="navbar-icon-links navbar-nav"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://twitter.com/ApacheArrow" title="X" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-x-twitter fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">X</span></a>
</li>
</ul></div>
</div>
</div>
<div class="navbar-persistent--mobile">
<script>
document.write(`
<button class="btn navbar-btn search-button-field search-button__button" 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>
`);
</script>
</div>
<label class="sidebar-toggle secondary-toggle" for="__secondary" tabindex="0">
<span class="fa-solid fa-outdent"></span>
</label>
</div>
</header>
<div class="bd-container">
<div class="bd-container__inner bd-page-width">
<div 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 class="navbar-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 dropdown">
<button class="btn dropdown-toggle nav-item" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-controls="pst-nav-more-links-2">
Implementations
</button>
<ul id="pst-nav-more-links-2" class="dropdown-menu">
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../c_glib/index.html">
C/GLib
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../cpp/index.html">
C++
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/csharp/README.md">
C#
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://pkg.go.dev/github.com/apache/arrow/go/v17">
Go
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../java/index.html">
Java
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../js/index.html">
JavaScript
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/julia/">
Julia
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/matlab/README.md">
MATLAB
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/nanoarrow/">
nanoarrow
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../python/index.html">
Python
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../r/index.html">
R
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://github.com/apache/arrow/blob/main/ruby/README.md">
Ruby
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://docs.rs/crate/arrow/">
Rust
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-internal" href="../../status.html">
Implementation Status
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/cpp/">
C++ cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/java/">
Java cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/py/">
Python cookbook
</a>
</li>
<li class="nav-item">
<a class="nav-link dropdown-item nav-external" href="https://arrow.apache.org/cookbook/r/">
R cookbook
</a>
</li>
</ul>
</li>
</ul>
</nav></div>
</div>
<div class="sidebar-header-items__end">
<div class="navbar-item">
<script>
document.write(`
<div class="version-switcher__container dropdown">
<button id="pst-version-switcher-button-3"
type="button"
class="version-switcher__button btn btn-sm navbar-btn 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>
`);
</script></div>
<div class="navbar-item">
<script>
document.write(`
<button class="btn btn-sm navbar-btn theme-switch-button" title="light/dark" aria-label="light/dark" data-bs-placement="bottom" data-bs-toggle="tooltip">
<span class="theme-switch nav-link" data-mode="light"><i class="fa-solid fa-sun fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="dark"><i class="fa-solid fa-moon fa-lg"></i></span>
<span class="theme-switch nav-link" data-mode="auto"><i class="fa-solid fa-circle-half-stroke fa-lg"></i></span>
</button>
`);
</script></div>
<div class="navbar-item"><ul class="navbar-icon-links navbar-nav"
aria-label="Icon Links">
<li class="nav-item">
<a href="https://github.com/apache/arrow" title="GitHub" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-github fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">GitHub</span></a>
</li>
<li class="nav-item">
<a href="https://twitter.com/ApacheArrow" title="X" class="nav-link" rel="noopener" target="_blank" data-bs-toggle="tooltip" data-bs-placement="bottom"><span><i class="fa-brands fa-square-x-twitter fa-lg" aria-hidden="true"></i></span>
<span class="sr-only">X</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="../Versioning.html">Format Versioning and Stability</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="../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><input checked="" class="toctree-checkbox" id="toctree-checkbox-1" name="toctree-checkbox-1" type="checkbox"/><label class="toctree-toggle" for="toctree-checkbox-1"><i class="fa-solid fa-chevron-down"></i></label><ul class="current">
<li class="toctree-l2 current active"><a class="current reference internal" href="#">The Arrow PyCapsule Interface</a></li>
</ul>
</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="../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 has-children"><a class="reference internal" href="../ADBC.html">ADBC: Arrow Database Connectivity</a><input class="toctree-checkbox" id="toctree-checkbox-2" name="toctree-checkbox-2" type="checkbox"/><label class="toctree-toggle" for="toctree-checkbox-2"><i class="fa-solid fa-chevron-down"></i></label><ul>
<li class="toctree-l2"><a class="reference internal" href="../ADBC/C.html">ADBC C API Specification</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ADBC/Go.html">ADBC Go API Specification</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ADBC/Java.html">ADBC Java API Specification</a></li>
</ul>
</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="../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>
<div id="rtd-footer-container"></div>
</div>
<main id="main-content" class="bd-main">
<div class="bd-content">
<div class="bd-article-container">
<div class="bd-header-article">
<div class="header-article-items header-article__inner">
<div class="header-article-items__start">
<div class="header-article-item">
<nav aria-label="Breadcrumb">
<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">The Arrow...</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="Permalink to this heading">#</a></h1>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>The Arrow PyCapsule Interface should be considered experimental</p>
</div>
<section id="rationale">
<h2>Rationale<a class="headerlink" href="#rationale" title="Permalink 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> and
<a class="reference internal" href="../CStreamInterface.html#c-stream-interface"><span class="std std-ref">C stream 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="Permalink 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>,
and <code class="docutils literal notranslate"><span class="pre">ArrowArrayStream</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="Permalink 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="Permalink 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>
<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>
</tbody>
</table>
<section id="lifetime-semantics">
<h3>Lifetime Semantics<a class="headerlink" href="#lifetime-semantics" title="Permalink 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>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="Permalink 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>
<section id="arrowschema-export">
<h3>ArrowSchema Export<a class="headerlink" href="#arrowschema-export" title="Permalink 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> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference external" href="https://docs.python.org/3/library/functions.html#object" title="(in Python v3.12)"><span class="pre">object</span></a></span></span><a class="headerlink" href="#arrow_c_schema__" title="Permalink 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="Permalink 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="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference external" href="https://docs.python.org/3/library/functions.html#object" title="(in Python v3.12)"><span class="pre">object</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.12)"><span class="pre">None</span></a></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><span class="pre">Tuple</span><span class="p"><span class="pre">[</span></span><a class="reference external" href="https://docs.python.org/3/library/functions.html#object" title="(in Python v3.12)"><span class="pre">object</span></a><span class="p"><span class="pre">,</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/functions.html#object" title="(in Python v3.12)"><span class="pre">object</span></a><span class="p"><span class="pre">]</span></span></span></span><a class="headerlink" href="#arrow_c_array__" title="Permalink 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>
</section>
<section id="arrowstream-export">
<h3>ArrowStream Export<a class="headerlink" href="#arrowstream-export" title="Permalink 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="p"><span class="pre">:</span></span><span class="w"> </span><span class="n"><a class="reference external" href="https://docs.python.org/3/library/functions.html#object" title="(in Python v3.12)"><span class="pre">object</span></a><span class="w"> </span><span class="p"><span class="pre">|</span></span><span class="w"> </span><a class="reference external" href="https://docs.python.org/3/library/constants.html#None" title="(in Python v3.12)"><span class="pre">None</span></a></span><span class="w"> </span><span class="o"><span class="pre">=</span></span><span class="w"> </span><span class="default_value"><span class="pre">None</span></span></em><span class="sig-paren">)</span> <span class="sig-return"><span class="sig-return-icon">&#x2192;</span> <span class="sig-return-typehint"><a class="reference external" href="https://docs.python.org/3/library/functions.html#object" title="(in Python v3.12)"><span class="pre">object</span></a></span></span><a class="headerlink" href="#arrow_c_stream__" title="Permalink 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>
</section>
<section id="schema-requests">
<h3>Schema Requests<a class="headerlink" href="#schema-requests" title="Permalink 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="protocol-typehints">
<h3>Protocol Typehints<a class="headerlink" href="#protocol-typehints" title="Permalink 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="nn">typing</span> <span class="kn">import</span> <span class="n">Tuple</span><span class="p">,</span> <span class="n">Protocol</span>
<span class="kn">from</span> <span class="nn">typing_extensions</span> <span class="kn">import</span> <span class="n">Self</span>
<span class="k">class</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="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="nc">ArrowArrayExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</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="nc">ArrowStreamExportable</span><span class="p">(</span><span class="n">Protocol</span><span class="p">):</span>
<span class="k">def</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>
</pre></div>
</div>
</section>
</section>
<section id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this heading">#</a></h2>
<section id="create-a-pycapsule">
<h3>Create a PyCapsule<a class="headerlink" href="#create-a-pycapsule" title="Permalink 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">
</input><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">
</input><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="nn">cpython</span>
<span class="k">from</span> <span class="nn">libc.stdlib</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="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="kt">ArrowSchema</span>* <span class="nf">schema</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="kt">object</span> <span class="nf">export_arrow_schema_py_capsule</span><span class="p">():</span>
<span class="k">cdef</span> <span class="kt">ArrowSchema</span>* <span class="nf">schema</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="Permalink 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">
</input><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">
</input><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="nn">cpython</span>
<span class="k">cdef</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="Permalink 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="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="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="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="nn">warnings</span>
<span class="c1"># NEW METHOD</span>
<span class="k">def</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="Permalink 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="Permalink 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="Permalink 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">
<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>
<div 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>
</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>
</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="#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 src="../../_static/scripts/bootstrap.js?digest=8d27b9dea8ad943066ae"></script>
<script src="../../_static/scripts/pydata-sphinx-theme.js?digest=8d27b9dea8ad943066ae"></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-2024 Apache Software Foundation.
Apache Arrow, Arrow, Apache, the Apache feather 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> 6.2.0.
<br/>
</p>
</div>
</div>
<div class="footer-items__end">
<div class="footer-item">
<p class="theme-version">
Built with the <a href="https://pydata-sphinx-theme.readthedocs.io/en/stable/index.html">PyData Sphinx Theme</a> 0.15.2.
</p></div>
</div>
</div>
</footer>
</body>
</html>