使用 C++ 和 Cython 程式碼中的 pyarrow#

pyarrow 同時提供 Cython 和 C++ API,讓您的原生程式碼能與 pyarrow 物件互動。

C++ API#

Arrow C++ 和 PyArrow C++ 標頭檔與 pyarrow 安裝包捆綁在一起。若要取得此目錄的絕對路徑 (如 numpy.get_include()),請使用

import pyarrow as pa
pa.get_include()

假設上述路徑在您的編譯器 include 路徑中,則可以使用以下指示詞包含 pyarrow API

#include <arrow/python/pyarrow.h>

這不會包含 Arrow API 的其他部分,您需要自行包含 (例如 arrow/api.h)。

建置使用 Arrow C++ 程式庫的 C 擴充功能時,您必須新增適當的連結器標記。我們提供了函數 pa.get_librariespa.get_library_dirs,它們會傳回程式庫名稱清單和可能的程式庫安裝位置 (如果您使用 pip 或 conda 安裝 pyarrow)。使用 setuptools 宣告您的 C 擴充功能時,必須包含這些 (請參閱下方)。

注意

PyArrow 特定的 C++ 程式碼現在是 PyArrow 原始碼樹的一部分,而不是 Arrow C++。這表示標頭檔和 arrow_python 程式庫不一定安裝在與 Arrow C++ 相同的位置,CMake 將不再自動找到它們。

初始化 API#

int import_pyarrow()#

初始化 pyarrow API 的內部指標。成功時,傳回 0。否則,傳回 -1 並設定 Python 例外。

在呼叫 pyarrow C++ API 中的任何其他函數之前,必須先呼叫此函數。若未執行此操作,很可能導致崩潰。

包裝與解包#

pyarrow 提供以下函數,可在 Python 包裝器 (由 pyarrow Python API 公開) 和底層 C++ 物件之間來回轉換。

bool arrow::py::is_array(PyObject *obj)#

傳回 obj 是否包裝 Arrow C++ Array 指標;換句話說,obj 是否為 pyarrow.Array 實例。

bool arrow::py::is_batch(PyObject *obj)#

傳回 obj 是否包裝 Arrow C++ RecordBatch 指標;換句話說,obj 是否為 pyarrow.RecordBatch 實例。

bool arrow::py::is_buffer(PyObject *obj)#

傳回 obj 是否包裝 Arrow C++ Buffer 指標;換句話說,obj 是否為 pyarrow.Buffer 實例。

bool arrow::py::is_data_type(PyObject *obj)#

傳回 obj 是否包裝 Arrow C++ DataType 指標;換句話說,obj 是否為 pyarrow.DataType 實例。

bool arrow::py::is_field(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ Field 指標;換句話說,obj 是否為 pyarrow.Field 實例。

bool arrow::py::is_scalar(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ Scalar 指標;換句話說,obj 是否為 pyarrow.Scalar 實例。

bool arrow::py::is_schema(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ Schema 指標;換句話說,obj 是否為 pyarrow.Schema 實例。

bool arrow::py::is_table(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ Table 指標;換句話說,obj 是否為 pyarrow.Table 實例。

bool arrow::py::is_tensor(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ Tensor 指標;換句話說,obj 是否為 pyarrow.Tensor 實例。

bool arrow::py::is_sparse_coo_tensor(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ SparseCOOTensor 指標;換句話說,obj 是否為 pyarrow.SparseCOOTensor 實例。

bool arrow::py::is_sparse_csc_matrix(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ SparseCSCMatrix 指標;換句話說,obj 是否為 pyarrow.SparseCSCMatrix 實例。

bool arrow::py::is_sparse_csf_tensor(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ SparseCSFTensor 指標;換句話說,obj 是否為 pyarrow.SparseCSFTensor 實例。

bool arrow::py::is_sparse_csr_matrix(PyObject *obj)#

傳回 obj 是否包裝了 Arrow C++ SparseCSRMatrix 指標;換句話說,obj 是否為 pyarrow.SparseCSRMatrix 實例。

以下函數預期一個 pyarrow 物件,解開底層的 Arrow C++ API 指標,並將其作為 Result 物件傳回。如果輸入物件不具有預期的類型,則可能會傳回錯誤。

Result<std::shared_ptr<Array>> arrow::py::unwrap_array(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Array 指標。

Result<std::shared_ptr<RecordBatch>> arrow::py::unwrap_batch(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ RecordBatch 指標。

Result<std::shared_ptr<Buffer>> arrow::py::unwrap_buffer(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Buffer 指標。

Result<std::shared_ptr<DataType>> arrow::py::unwrap_data_type(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ DataType 指標。

Result<std::shared_ptr<Field>> arrow::py::unwrap_field(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Field 指標。

Result<std::shared_ptr<Scalar>> arrow::py::unwrap_scalar(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Scalar 指標。

Result<std::shared_ptr<Schema>> arrow::py::unwrap_schema(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Schema 指標。

Result<std::shared_ptr<Table>> arrow::py::unwrap_table(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Table 指標。

Result<std::shared_ptr<Tensor>> arrow::py::unwrap_tensor(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ Tensor 指標。

Result<std::shared_ptr<SparseCOOTensor>> arrow::py::unwrap_sparse_coo_tensor(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ SparseCOOTensor 指標。

Result<std::shared_ptr<SparseCSCMatrix>> arrow::py::unwrap_sparse_csc_matrix(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ SparseCSCMatrix 指標。

Result<std::shared_ptr<SparseCSFTensor>> arrow::py::unwrap_sparse_csf_tensor(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ SparseCSFTensor 指標。

Result<std::shared_ptr<SparseCSRMatrix>> arrow::py::unwrap_sparse_csr_matrix(PyObject *obj)#

解開並從 obj 傳回 Arrow C++ SparseCSRMatrix 指標。

以下函數接受一個 Arrow C++ API 指標,並將其包裝成相應類型的 pyarray 物件。將傳回一個新的參考。如果發生錯誤,則傳回 NULL 並設定一個 Python 例外。

PyObject *arrow::py::wrap_array(const std::shared_ptr<Array> &array)#

將 Arrow C++ array 包裝在 pyarrow.Array 實例中。

PyObject *arrow::py::wrap_batch(const std::shared_ptr<RecordBatch> &batch)#

將 Arrow C++ 紀錄 batch 包裝在 pyarrow.RecordBatch 實例中。

PyObject *arrow::py::wrap_buffer(const std::shared_ptr<Buffer> &buffer)#

將 Arrow C++ buffer 包裝在 pyarrow.Buffer 實例中。

PyObject *arrow::py::wrap_data_type(const std::shared_ptr<DataType> &data_type)#

將 Arrow C++ data_type 包裝在 pyarrow.DataType 實例中。

PyObject *arrow::py::wrap_field(const std::shared_ptr<Field> &field)#

將 Arrow C++ 的 field 包裝在 pyarrow.Field 實例中。

PyObject *arrow::py::wrap_scalar(const std::shared_ptr<Scalar> &scalar)#

將 Arrow C++ 的 scalar 包裝在 pyarrow.Scalar 實例中。

PyObject *arrow::py::wrap_schema(const std::shared_ptr<Schema> &schema)#

將 Arrow C++ 的 schema 包裝在 pyarrow.Schema 實例中。

PyObject *arrow::py::wrap_table(const std::shared_ptr<Table> &table)#

將 Arrow C++ 的 table 包裝在 pyarrow.Table 實例中。

PyObject *arrow::py::wrap_tensor(const std::shared_ptr<Tensor> &tensor)#

將 Arrow C++ 的 tensor 包裝在 pyarrow.Tensor 實例中。

PyObject *arrow::py::wrap_sparse_coo_tensor(const std::shared_ptr<SparseCOOTensor> &sparse_tensor)#

將 Arrow C++ 的 sparse_tensor 包裝在 pyarrow.SparseCOOTensor 實例中。

PyObject *arrow::py::wrap_sparse_csc_matrix(const std::shared_ptr<SparseCSCMatrix> &sparse_tensor)#

將 Arrow C++ 的 sparse_tensor 包裝在 pyarrow.SparseCSCMatrix 實例中。

PyObject *arrow::py::wrap_sparse_csf_tensor(const std::shared_ptr<SparseCSFTensor> &sparse_tensor)#

將 Arrow C++ 的 sparse_tensor 包裝在 pyarrow.SparseCSFTensor 實例中。

PyObject *arrow::py::wrap_sparse_csr_matrix(const std::shared_ptr<SparseCSRMatrix> &sparse_tensor)#

將 Arrow C++ 的 sparse_tensor 包裝在 pyarrow.SparseCSRMatrix 實例中。

Cython API#

Cython API 或多或少地反映了 C++ API,但呼叫慣例可能會因 Cython 的需求而有所不同。在 Cython 中,您不需要初始化 API,因為這將由 cimport 指令自動處理。

注意

來自 Arrow C++ API 的類別在 Cython 中公開時會被重新命名,以避免與對應的 Python 類別發生名稱衝突。例如,C++ Arrow 陣列具有 CArray 類型,而 Array 是對應的 Python 包裝器類別。

包裝與解包#

以下函式預期一個 pyarrow 物件,解包底層的 Arrow C++ API 指標,並將其傳回。如果輸入不是正確的類型,則傳回 NULL(且不設定例外)。

pyarrow.pyarrow_unwrap_array(obj) shared_ptr[CArray]#

obj 解包 Arrow C++ Array 指標。

pyarrow.pyarrow_unwrap_batch(obj) shared_ptr[CRecordBatch]#

obj 解包 Arrow C++ RecordBatch 指標。

pyarrow.pyarrow_unwrap_buffer(obj) shared_ptr[CBuffer]#

obj 解包 Arrow C++ Buffer 指標。

pyarrow.pyarrow_unwrap_data_type(obj) shared_ptr[CDataType]#

obj 解包 Arrow C++ CDataType 指標。

pyarrow.pyarrow_unwrap_field(obj) shared_ptr[CField]#

obj 解包 Arrow C++ Field 指標。

pyarrow.pyarrow_unwrap_scalar(obj) shared_ptr[CScalar]#

obj 解包 Arrow C++ Scalar 指標。

pyarrow.pyarrow_unwrap_schema(obj) shared_ptr[CSchema]#

obj 解包 Arrow C++ Schema 指標。

pyarrow.pyarrow_unwrap_table(obj) shared_ptr[CTable]#

obj 解包 Arrow C++ Table 指標。

pyarrow.pyarrow_unwrap_tensor(obj) shared_ptr[CTensor]#

obj 解包 Arrow C++ Tensor 指標。

pyarrow.pyarrow_unwrap_sparse_coo_tensor(obj) shared_ptr[CSparseCOOTensor]#

obj 解包 Arrow C++ SparseCOOTensor 指標。

pyarrow.pyarrow_unwrap_sparse_csc_matrix(obj) shared_ptr[CSparseCSCMatrix]#

obj 解包 Arrow C++ SparseCSCMatrix 指標。

pyarrow.pyarrow_unwrap_sparse_csf_tensor(obj) shared_ptr[CSparseCSFTensor]#

obj 解包 Arrow C++ SparseCSFTensor 指標。

pyarrow.pyarrow_unwrap_sparse_csr_matrix(obj) shared_ptr[CSparseCSRMatrix]#

obj 解包 Arrow C++ SparseCSRMatrix 指標。

以下函式接受 Arrow C++ API 指標,並將其包裝在對應類型的 pyarray 物件中。錯誤時會引發例外。

pyarrow.pyarrow_wrap_array(const shared_ptr[CArray]& array) object#

將 Arrow C++ array 包裝在 Python pyarrow.Array 實例中。

pyarrow.pyarrow_wrap_batch(const shared_ptr[CRecordBatch]& batch) object#

將 Arrow C++ 記錄批次包裝在 Python pyarrow.RecordBatch 實例中。

pyarrow.pyarrow_wrap_buffer(const shared_ptr[CBuffer]& buffer) object#

將 Arrow C++ buffer 包裝在 Python pyarrow.Buffer 實例中。

pyarrow.pyarrow_wrap_data_type(const shared_ptr[CDataType]& data_type) object#

將 Arrow C++ data_type 包裝在 Python pyarrow.DataType 實例中。

pyarrow.pyarrow_wrap_field(const shared_ptr[CField]& field) object#

將 Arrow C++ field 包裝在 Python pyarrow.Field 實例中。

pyarrow.pyarrow_wrap_resizable_buffer(const shared_ptr[CResizableBuffer]& buffer) object#

將 Arrow C++ 可調整大小的 buffer 包裝在 Python pyarrow.ResizableBuffer 實例中。

pyarrow.pyarrow_wrap_scalar(const shared_ptr[CScalar]& scalar) object#

將 Arrow C++ scalar 包裝在 Python pyarrow.Scalar 實例中。

pyarrow.pyarrow_wrap_schema(const shared_ptr[CSchema]& schema) object#

將 Arrow C++ schema 包裝在 Python pyarrow.Schema 實例中。

pyarrow.pyarrow_wrap_table(const shared_ptr[CTable]& table) object#

將 Arrow C++ table 包裝在 Python pyarrow.Table 實例中。

pyarrow.pyarrow_wrap_tensor(const shared_ptr[CTensor]& tensor) object#

將 Arrow C++ tensor 包裝在 Python pyarrow.Tensor 實例中。

pyarrow.pyarrow_wrap_sparse_coo_tensor(const shared_ptr[CSparseCOOTensor]& sparse_tensor) object#

將 Arrow C++ COO 稀疏張量包裝在 Python pyarrow.SparseCOOTensor 實例中。

pyarrow.pyarrow_wrap_sparse_csc_matrix(const shared_ptr[CSparseCSCMatrix]& sparse_tensor) object#

將 Arrow C++ CSC 稀疏張量包裝在 Python pyarrow.SparseCSCMatrix 實例中。

pyarrow.pyarrow_wrap_sparse_csf_tensor(const shared_ptr[CSparseCSFTensor]& sparse_tensor) object#

將 Arrow C++ COO 稀疏張量包裝在 Python pyarrow.SparseCSFTensor 實例中。

pyarrow.pyarrow_wrap_sparse_csr_matrix(const shared_ptr[CSparseCSRMatrix]& sparse_tensor) object#

將 Arrow C++ CSR 稀疏張量包裝在 Python pyarrow.SparseCSRMatrix 實例中。

範例#

以下 Cython 模組展示了如何解包 Python 物件並呼叫底層 C++ 物件的 API。

# distutils: language=c++

from pyarrow.lib cimport *


def get_array_length(obj):
    # Just an example function accessing both the pyarrow Cython API
    # and the Arrow C++ API
    cdef shared_ptr[CArray] arr = pyarrow_unwrap_array(obj)
    if arr.get() == NULL:
        raise TypeError("not an array")
    return arr.get().length()

要建置此模組,您需要稍微客製化的 setup.py 檔案(假設上面的檔案名為 example.pyx

from setuptools import setup
from Cython.Build import cythonize

import os
import numpy as np
import pyarrow as pa


ext_modules = cythonize("example.pyx")

for ext in ext_modules:
    # The Numpy C headers are currently required
    ext.include_dirs.append(np.get_include())
    ext.include_dirs.append(pa.get_include())
    ext.libraries.extend(pa.get_libraries())
    ext.library_dirs.extend(pa.get_library_dirs())

    if os.name == 'posix':
        ext.extra_compile_args.append('-std=c++17')

setup(ext_modules=ext_modules)

編譯擴充功能

python setup.py build_ext --inplace

針對 PyPI Wheels 建置擴充功能#

Python wheel 在頂層 pyarrow/ 安裝目錄中捆綁了 Arrow C++ 程式庫。在 Linux 和 macOS 上,這些程式庫具有類似 libarrow.so.17 的 ABI 標籤,這意味著使用 pyarrow.get_library_dirs() 提供的連結器路徑,並使用 -larrow 進行連結,將無法直接運作。為了修正這個問題,您必須以具有 pyarrow 安裝目錄寫入權限的使用者身分,執行一次 pyarrow.create_library_symlinks()。此函數將嘗試建立類似 pyarrow/libarrow.so 的符號連結。例如:

pip install pyarrow
python -c "import pyarrow; pyarrow.create_library_symlinks()"

工具鏈相容性(Linux)#

Linux 的 Python wheel 是使用 PyPA manylinux 映像檔 建置的,該映像檔使用 CentOS devtoolset-9。除了上述其他注意事項外,如果您使用這些共享程式庫編譯 C++,則還需要確保您也使用相容的工具鏈,否則您可能會在執行時看到區段錯誤(segfault)。