Cython:“致命错误:numpy/arrayobject.h:没有这样的文件或目录”

Posted

技术标签:

【中文标题】Cython:“致命错误:numpy/arrayobject.h:没有这样的文件或目录”【英文标题】:Cython: "fatal error: numpy/arrayobject.h: No such file or directory" 【发布时间】:2013-01-17 10:03:40 【问题描述】:

我正在尝试使用 Cython 加快回答 here 的速度。我尝试编译代码(在完成cygwinccompiler.py hack 解释here 之后),但得到fatal error: numpy/arrayobject.h: No such file or directory...compilation terminated 错误。谁能告诉我这是我的代码有问题,还是 Cython 有一些深奥的微妙之处?

下面是我的代码。

import numpy as np
import scipy as sp
cimport numpy as np
cimport cython

cdef inline np.ndarray[np.int, ndim=1] fbincount(np.ndarray[np.int_t, ndim=1] x):
    cdef int m = np.amax(x)+1
    cdef int n = x.size
    cdef unsigned int i
    cdef np.ndarray[np.int_t, ndim=1] c = np.zeros(m, dtype=np.int)

    for i in xrange(n):
        c[<unsigned int>x[i]] += 1

    return c

cdef packed struct Point:
    np.float64_t f0, f1

@cython.boundscheck(False)
def sparsemaker(np.ndarray[np.float_t, ndim=2] X not None,
                np.ndarray[np.float_t, ndim=2] Y not None,
                np.ndarray[np.float_t, ndim=2] Z not None):

    cdef np.ndarray[np.float64_t, ndim=1] counts, factor
    cdef np.ndarray[np.int_t, ndim=1] row, col, repeats
    cdef np.ndarray[Point] indices

    cdef int x_, y_

    _, row = np.unique(X, return_inverse=True); x_ = _.size
    _, col = np.unique(Y, return_inverse=True); y_ = _.size
    indices = np.rec.fromarrays([row,col])
    _, repeats = np.unique(indices, return_inverse=True)
    counts = 1. / fbincount(repeats)
    Z.flat *= counts.take(repeats)

    return sp.sparse.csr_matrix((Z.flat,(row,col)), shape=(x_, y_)).toarray()

【问题讨论】:

您可以为您使用的操作系统添加标签吗? @tcaswell 64 位 Windows 7。 添加了 windows 标签,希望这将有助于知道如何使用 windows 的人(不像我)看到这个问题。 我找到了this。有些术语在我头上,但我要检查一下。 这能回答你的问题吗? Make distutils look for numpy header files in the correct place 【参考方案1】:

该错误表示编译期间未找到 numpy 头文件。

尝试做export CFLAGS=-I/usr/lib/python2.7/site-packages/numpy/core/include/,然后编译。这是几个不同软件包的问题。 ArchLinux 中针对同一问题提交了一个错误:https://bugs.archlinux.org/task/22326

【讨论】:

在哪里添加export 行?在我的setup.py 文件中? 不,这是一个 shell 命令。在你的 shell 中运行它,然后开始编译。 @NoobSaibot 在 shell 中(运行 python setup.py)首先运行 export .. 命令。它设置 shell 的环境变量,与 [pc]ython 没有任何直接关系。 @tcaswell:我也这么认为。我正在使用 cmd,并得到了这个 'export' is not recognized as an internal or external command, operable program or batch file. 错误......只是无法用这个获胜...... @NoobSaibot 你得到了 lunix 的答案,因为你闻起来像 Windows 问题......【参考方案2】:

在您的setup.py 中,Extension 应该有参数include_dirs=[numpy.get_include()]

另外,您的代码中缺少np.import_array()

--

setup.py 示例:

from distutils.core import setup, Extension
from Cython.Build import cythonize
import numpy

setup(
    ext_modules=[
        Extension("my_module", ["my_module.c"],
                  include_dirs=[numpy.get_include()]),
    ],
)

# Or, if you use cythonize() to make the ext_modules list,
# include_dirs can be passed to setup()

setup(
    ext_modules=cythonize("my_module.pyx"),
    include_dirs=[numpy.get_include()]
)    

【讨论】:

我为什么需要np.import_array()?不是Numpy C-API吗? 我尝试了你的想法,但现在我收到了这个太长的疯狂错误,无法在此处发布,但它以 warning: untitled.pyx:8:49: Buffer unpacking not optimized away. 开头 啊,没错,你可能不需要np.import_array()。不过,我很少在没有它的情况下编写使用 numpy 的 Cython 扩展,所以我习惯于使用它。至于您的其他问题,您引用的只是警告,而不是错误。如果您还有其他需要修复的错误,请发新帖。 include_dirs=[numpy.get_include()] 是个好技巧,谢谢! include_dirs 传递给 setup() 在最新的 distutils 中被忽略,它必须传递给每个 Extension,至少在 mac 上【参考方案3】:

对于像您这样的单文件项目,另一种选择是使用pyximport。你不需要创建setup.py ...如果你使用IPython,你甚至不需要打开命令行...这一切都非常方便。在您的情况下,请尝试在 IPython 或普通 Python 脚本中运行这些命令:

import numpy
import pyximport
pyximport.install(setup_args="script_args":["--compiler=mingw32"],
                              "include_dirs":numpy.get_include(),
                  reload_support=True)

import my_pyx_module

print my_pyx_module.some_function(...)
...

当然,您可能需要编辑编译器。这使得 .pyx 文件的导入和重新加载工作与 .py 文件的工作方式相同。

来源:http://wiki.cython.org/InstallingOnWindows

【讨论】:

谢谢@SteveB。但是您能否详细说明“对于像您这样的单文件项目 ...”的含义?上面的模块是一个更大的应用程序的一个(尽管很重要)部分。 pyximport 如何影响我的代码速度?最后,这里的部分:"Since Cython 0.11, the pyximport module also has experimental compilation support for normal Python modules..." 暗示它仍有一些问题需要解决。你能解释一下吗? 关于“对普通 Python 模块的实验性编译支持”——使用我上面建议的代码,.py 模块可以正常编译(不使用 cython),而 .pyx 模块使用 cython 编译。如果您将pyimport = True 传递给pyximport.install(),那么它将使用cython 处理所有内容,甚至例如import randomimport os。我不建议使用该功能,仅仅是因为没有令人信服的理由来使用它,而且它可能会产生问题。它可能主要由 cython 开发人员使用。 如果pyximport 工作正常,它将创建与任何其他方法完全相同的 C 代码。所以试试看。我指的是当编译过程足够复杂时,例如指向外部系统库的链接,您可能会发现 pyximport 失败,您需要 setup.pycythonize 来准确指定如何构建它。但是你的.pyx 模块有imports 或cimports 并不意味着它不能用pyximport 编译;可能完全没问题。 这很好用!但如果你已经安装了 msvc,我推荐 --compiler=msvc。那你就不需要安装mingw了。【参考方案4】:

简单回答

一种更简单的方法是将路径添加到您的文件distutils.cfg。默认情况下,它代表 Windows 7 的路径是C:\Python27\Lib\distutils\。您只需断言以下内容,它应该可以解决:

[build_ext]
include_dirs= C:\Python27\Lib\site-packages\numpy\core\include

整个配置文件

为了给你一个配置文件的例子,我的整个文件如下:

[build]
compiler = mingw32

[build_ext]
include_dirs= C:\Python27\Lib\site-packages\numpy\core\include
compiler = mingw32

【讨论】:

【参考方案5】:

它应该可以在cythonize() 提到的here 函数中执行此操作,但它不起作用,因为有一个known issue

【讨论】:

【参考方案6】:

如果你懒得写设置文件和找出包含目录的路径, 试试cyper。它可以编译你的 Cython 代码并自动为 Numpy 设置include_dirs

将您的代码加载到一个字符串中,然后简单地运行cymodule = cyper.inline(code_string),然后您的函数就可以立即作为cymodule.sparsemaker 使用。像这样的

code = open(your_pyx_file).read()
cymodule = cyper.inline(code)

cymodule.sparsemaker(...)
# do what you want with your function

您可以通过pip install cyper 安装cyper。

【讨论】:

【参考方案7】:

根据this answer,如果您在Linux上安装了numpypip,则需要手动设置/usr/include/numpy的符号链接

就我而言,路径是:

sudo ln -s /usr/local/lib/python3.8/dist-packages/numpy/core/include/numpy/ /usr/include/numpy

【讨论】:

【参考方案8】:

我在运行的服务器上没有 sudo 权限,并且导出 CFLAGS 对我不起作用。为了简单起见,我安装了 Anaconda ( https://docs.anaconda.com/anaconda/install/) 创建指向所有已安装包的链接,包括 Numpy。您还可以安装 miniconda 并使用环境以避免占用过多空间。

【讨论】:

你确定这回答了这个问题吗?请阅读How to Answer。

以上是关于Cython:“致命错误:numpy/arrayobject.h:没有这样的文件或目录”的主要内容,如果未能解决你的问题,请参考以下文章

为整个程序启用 Cython 分析?

Cython 是什么?为什么会有 Cython?

Cython 是什么?为什么会有 Cython?

在 Cython 中使用 C++ STL 映射

Cython初窥

在 C++ 中嵌入 Cython