使用MemoryView时,Cython Numpy警告NPY_NO_DEPRECATED_API。

43
我正在将一个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的问题。我只是将memoryview转换为一个numpy数组。还有其他更简洁/更安全的方法吗?


2
就我而言,我也收到了同样的警告。目前还没有影响到什么,所以我暂时忽略它们。 - perimosocordiae
define_macrosinclude_dirs 移动到 setup - Demetry Pascal
4个回答

49

仅供参考,根据Cython在线文档,这是因为Cython正在使用已弃用的Numpy API,暂时只是一个可以忽略的警告。


3
谢谢!我选择了你的答案,因为它不仅是你的猜测,而且你还提供了证据。 :) - Amenhotep
1
好的,但是警告信息会被写入标准输出,所以过滤起来很麻烦。有没有办法配置Cython不报告警告信息? - Arthur
1
@Arthur 如果你在IPython中使用Cython魔法,那么你可以使用%%cython --compile-args=-w来禁用警告。 - towr
1
在线文档部分已经迁移到http://docs.cython.org/en/latest/src/userguide/source_files_and_compilation.html#configuring-the-c-build。 - Demi-Lune
总结一下上述文档:截至2021年,Cython 3.0版本(仍处于预发布阶段)解决了该问题,早期的Cython版本则会忽略此警告。 - Nikolay

1

Cython文档说

In Cython 3.0, you can get rid of this warning by defining the C macro NPY_NO_DEPRECATED_API as NPY_1_7_API_VERSION in your build:

# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION

...

With older Cython releases, setting this macro will fail the C compilation, because Cython generates code that uses this deprecated C-API. However, the warning has no negative effects even in recent NumPy versions including 1.18.x. You can ignore it until you (or your library’s users) switch to a newer NumPy version that removes this long deprecated API, in which case you also need to use Cython 3.0 or later. Thus, the earlier you switch to Cython 3.0, the better for your users.

截至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的这种方法,在我使用的功能子集中没有任何问题。


1
非常好的回答!既有“为什么”的部分,也有“如何”的部分。 - Antony Hatchkins
1
Cython 3.0 于今年七月发布。 - Samufi

0

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

使用numpy C API时,如果你不喜欢这个警告,你需要在C脚本前面加上一行代码,但它只是告诉编译器忽略这个“已弃用”的消息 - 无论哪种方式都能正常工作。

我猜测Cython编译器在生成C代码时没有加入这行代码,但我认为这并不重要。


0
假设有人希望隐藏弃用警告,可以使用以下编译器标志来实现clang:extra_compile_args=['-Wno-#warnings']
对于gcc,extra_compile_args=['-Wno-cpp']也可以达到相同的效果。
当然,这也会隐藏其他预处理指令警告。

3
贬低警告是一种不好的习惯。 - Maksym Ganenko

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接