使用MemoryView时关于NPY_NO_DEPRECATED_API的Cython Numpy警告



我正在将Cython内存视图转换为numpy数组(以便能够在纯Python代码中使用它):

from libc.stdlib cimport realloc
cimport numpy as np
DTYPE = np.float64
ctypedef np.float64_t DTYPE_t
cpdef np.ndarray[DTYPE_t] compute(DTYPE_t[:,::1] data):
    cdef unsigned int Nchannels = data.shape[0]
    cdef unsigned int Ndata = data.shape[1]
    cdef DTYPE_t* output = NULL
    cdef DTYPE_t[::1] mv
    output = <DTYPE_t*>realloc(output, Ndata*sizeof(output))
    if not output:
        raise MemoryError()
    mv = <DTYPE_t[:Ndata]>output
    mv[10:Ndata-10] = 0.0
    # various calculations...
    return np.asarray(mv, dtype=DTYPE, order='C')

它进行编译,但编译器会发出以下警告:

/Users/vlad/anaconda/lib/python2.7/site-packages/numpy/core/include
/nump/npy_1_7_deprecated_api.h:15:2: warning:
"Using deprecated NumPy API, disable it by #defining NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION" [-W#warnings]

我在setup.py:中添加了建议的指令

from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy
filename = 'agents3.pyx'
agents_module = Extension(
    'Agents',
    sources = [filename],
    define_macros = [('NPY_NO_DEPRECATED_API', 'NPY_1_7_API_VERSION')],
    include_dirs = [numpy.get_include()],
)
setup (name = 'Agents',
    ext_modules = cythonize(agents_module)
)

现在它不会编译了,它说:

Vlads-MacBook-Pro:program vlad$ python setup.py build_ext --inplace
Compiling agents3.pyx because it changed.
Cythonizing agents3.pyx
running build_ext
building 'Agents' extension
gcc -fno-strict-aliasing -I/Users/vlad/anaconda/include -arch x86_64 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -I/Users/vlad/anaconda/lib/python2.7/site-packages/numpy/core/include -I/Users/vlad/anaconda/include/python2.7 -c agents3.c -o build/temp.macosx-10.5-x86_64-2.7/agents3.o
agents3.c:2273:52: error: use of undeclared identifier 'NPY_C_CONTIGUOUS'
    __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS) != 0)) != 0);
                                                   ^
agents3.c:2311:52: error: use of undeclared identifier 'NPY_F_CONTIGUOUS'
    __pyx_t_1 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS) != 0)) != 0);
                                                   ^
agents3.c:2474:42: error: no member named 'descr' in 'struct tagPyArrayObject'
  __pyx_t_4 = ((PyObject *)__pyx_v_self->descr);
                           ~~~~~~~~~~~~  ^
agents3.c:4026:27: error: no member named 'base' in 'struct tagPyArrayObject'
  Py_XDECREF(__pyx_v_arr->base);
             ~~~~~~~~~~~  ^
/Users/vlad/anaconda/include/python2.7/object.h:823:34: note: expanded from macro 'Py_XDECREF'
#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
                                 ^
agents3.c:4026:27: error: no member named 'base' in 'struct tagPyArrayObject'
  Py_XDECREF(__pyx_v_arr->base);
             ~~~~~~~~~~~  ^
/Users/vlad/anaconda/include/python2.7/object.h:823:64: note: expanded from macro 'Py_XDECREF'
#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
                                                               ^
/Users/vlad/anaconda/include/python2.7/object.h:772:24: note: expanded from macro 'Py_DECREF'
        --((PyObject*)(op))->ob_refcnt != 0)            
                       ^
agents3.c:4026:27: error: no member named 'base' in 'struct tagPyArrayObject'
  Py_XDECREF(__pyx_v_arr->base);
             ~~~~~~~~~~~  ^
/Users/vlad/anaconda/include/python2.7/object.h:823:64: note: expanded from macro 'Py_XDECREF'
#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
                                                               ^
/Users/vlad/anaconda/include/python2.7/object.h:775:34: note: expanded from macro 'Py_DECREF'
        _Py_Dealloc((PyObject *)(op));                  
                                 ^
/Users/vlad/anaconda/include/python2.7/object.h:762:15: note: expanded from macro '_Py_Dealloc'
    (*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))
              ^
/Users/vlad/anaconda/include/python2.7/object.h:115:47: note: expanded from macro 'Py_TYPE'
#define Py_TYPE(ob)             (((PyObject*)(ob))->ob_type)
                                              ^
agents3.c:4026:27: error: no member named 'base' in 'struct tagPyArrayObject'
  Py_XDECREF(__pyx_v_arr->base);
             ~~~~~~~~~~~  ^
/Users/vlad/anaconda/include/python2.7/object.h:823:64: note: expanded from macro 'Py_XDECREF'
#define Py_XDECREF(op) do { if ((op) == NULL) ; else Py_DECREF(op); } while (0)
                                                               ^
/Users/vlad/anaconda/include/python2.7/object.h:775:34: note: expanded from macro 'Py_DECREF'
        _Py_Dealloc((PyObject *)(op));                  
                                 ^
/Users/vlad/anaconda/include/python2.7/object.h:762:45: note: expanded from macro '_Py_Dealloc'
    (*Py_TYPE(op)->tp_dealloc)((PyObject *)(op)))
                                            ^
agents3.c:4035:16: error: no member named 'base' in 'struct tagPyArrayObject'
  __pyx_v_arr->base = __pyx_v_baseptr;
  ~~~~~~~~~~~  ^
agents3.c:4070:30: error: no member named 'base' in 'struct tagPyArrayObject'
  __pyx_t_1 = ((__pyx_v_arr->base == NULL) != 0);
                ~~~~~~~~~~~  ^
agents3.c:4093:44: error: no member named 'base' in 'struct tagPyArrayObject'
    __Pyx_INCREF(((PyObject *)__pyx_v_arr->base));
                              ~~~~~~~~~~~  ^
agents3.c:1065:37: note: expanded from macro '__Pyx_INCREF'
  #define __Pyx_INCREF(r) Py_INCREF(r)
                                    ^
/Users/vlad/anaconda/include/python2.7/object.h:767:18: note: expanded from macro 'Py_INCREF'
    ((PyObject*)(op))->ob_refcnt++)
                 ^
agents3.c:4094:41: error: no member named 'base' in 'struct tagPyArrayObject'
    __pyx_r = ((PyObject *)__pyx_v_arr->base);
                           ~~~~~~~~~~~  ^
11 errors generated.
error: command 'gcc' failed with exit status 1
Vlads-MacBook-Pro:program vlad$ 

我该怎么办?保留不推荐使用的API调用可以吗?它试图访问base字段,但我没有这么做,这是Cython的错。我只是简单地将内存视图转换为numpy数组。还有其他更清洁/更安全的方法吗?

只是为了进一步参考,cython在线文档表示,这是因为cython使用了一个不推荐使用的Numpy API,目前,这只是一个我们可以忽略的警告。

Cython文档说明:

在Cython 3.0中,您可以通过在构建中将C宏NPY_NO_DEPRECATED_API定义为NPY_1_7_API_VERSION来消除此警告:

# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION

对于较旧的Cython版本,设置此宏将使C编译失败,因为Cython生成的代码使用此不推荐使用的C-API。然而,即使在最近的NumPy版本(包括1.18.x.)中,该警告也没有负面影响。您可以忽略它,直到您(或库的用户)切换到删除此长期不推荐使用的API的新NumPy版本,在这种情况下,您还需要使用Cython 3.0或更高版本。因此,您越早切换到Cython 3.0,对您的用户就越好

截至2023年2月,Cython 3.0尚未发布,因此升级到Cython 3.0以删除警告的建议并不成熟。

你可以忽略它建议也不是最好的做法,因为它会导致开发人员的疲劳、冷漠和无知,从而导致错误。

在早期的Cython版本中,可以通过定义C预处理器宏NPY_NO_DEPRECATED_API=1来禁用此警告,例如:

# distutils: define_macros=NPY_NO_DEPRECATED_API=1

我将这个方法与cython-0.29.32和numpy-1.23.4一起使用,在我使用的功能子集中没有问题。

我也收到了同样的警告,我认为这很正常。

对于numpy C API,如果你不喜欢这个警告,你需要在C脚本前面放一行,但它所做的只是告诉编译器忽略"不推荐使用"的消息-无论哪种方式,它似乎都一样。

我猜Cython编译器在生成C代码时不会放这行代码,我认为这并不重要。

假设希望隐藏弃用警告,则可以使用clang实现以下编译器标志:extra_compile_args=['-Wno-#warnings']

对于gcc,extra_compile_args=['-Wno-cpp']实现了相同的效果。

当然,这也隐藏了其他预处理器指令警告。

相关内容

  • 没有找到相关文章

最新更新