在 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()
假设上述路径在您的编译器的包含路径中,可以使用以下指令包含 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 指针,并将其封装在相应类型的 pyarrow 对象中。如果出错,则会引发异常。
- 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++ 记录 batch 包装成 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 包中捆绑了 Arrow C++ 库,位于 pyarrow/ 安装目录的顶层。在 Linux 和 macOS 上,这些库具有 ABI 标签,例如 libarrow.so.17,这意味着使用 -larrow 并使用 pyarrow.get_library_dirs() 提供的链接器路径将无法直接工作。要解决此问题,您必须以对 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++,您还需要确保使用兼容的工具链,否则您可能会在运行时遇到段错误。