使用 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_libraries
和 pa.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 例外。
將 Arrow C++ array 包裝在
pyarrow.Array
實例中。
將 Arrow C++ 紀錄 batch 包裝在
pyarrow.RecordBatch
實例中。
將 Arrow C++ buffer 包裝在
pyarrow.Buffer
實例中。
將 Arrow C++ data_type 包裝在
pyarrow.DataType
實例中。
將 Arrow C++ 的 field 包裝在
pyarrow.Field
實例中。
將 Arrow C++ 的 scalar 包裝在
pyarrow.Scalar
實例中。
將 Arrow C++ 的 schema 包裝在
pyarrow.Schema
實例中。
將 Arrow C++ 的 table 包裝在
pyarrow.Table
實例中。
將 Arrow C++ 的 tensor 包裝在
pyarrow.Tensor
實例中。
將 Arrow C++ 的 sparse_tensor 包裝在
pyarrow.SparseCOOTensor
實例中。
將 Arrow C++ 的 sparse_tensor 包裝在
pyarrow.SparseCSCMatrix
實例中。
將 Arrow C++ 的 sparse_tensor 包裝在
pyarrow.SparseCSFTensor
實例中。
將 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_batch(obj) shared_ptr[CRecordBatch] #
從 obj 解包 Arrow C++
RecordBatch
指標。
- pyarrow.pyarrow_unwrap_data_type(obj) shared_ptr[CDataType] #
從 obj 解包 Arrow C++
CDataType
指標。
- 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
實例中。
範例#
以下 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)。