Cython: «фатальная ошибка: numpy / arrayobject.h: нет такого файла или каталога»

133

Я пытаюсь ускорить ответ здесь с помощью Cython. Я пытаюсь скомпилировать код (после выполнения cygwinccompiler.pyописанного здесь взлома ), но получаю сообщение 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()
Нуб сайбот
источник
вы можете добавить тег для какой ОС вы используете?
tacaswell
@tcaswell 64-битная Windows 7.
Noob Saibot
добавлен тег windows, надеюсь, это поможет увидеть эту проблему людям, которые умеют использовать окна (в отличие от меня).
tacaswell
1
Я нашел это . Некоторая терминология у меня над головой, но я собираюсь проверить это.
Нуб Сайбот

Ответы:

186

В ваших 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()]
)    
Роберт Керн
источник
4
Зачем мне это нужно np.import_array()? Разве это не для Numpy C-API ?
Нуб Сайбот
Я попробовал вашу идею, но теперь получаю эту сумасшедшую ошибку, которую нельзя публиковать здесь, но она начинается сwarning: untitled.pyx:8:49: Buffer unpacking not optimized away.
Noob Saibot
Ах, правда, тебе наверное не нужно np.import_array(). Однако я редко пишу расширения Cython, использующие numpy, без него, поэтому я использую его по привычке. Что касается другой вашей проблемы, то, что вы процитировали, является просто предупреждением, а не ошибкой. Если у вас есть другие ошибки, которые необходимо исправить, напишите новое сообщение.
Роберт Керн
1
include_dirs=[numpy.get_include()]это хороший трюк, спасибо!
Дэниел Фаррелл,
14
include_dirsпереданный setup()игнорируется в последних distutils, он должен быть передан каждому Extension, по крайней мере, на Mac
dashesy
45

Для однофайлового проекта, подобного вашему, другой альтернативой является использование 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влияет на скорость моего кода? И, наконец, раздел здесь: « Начиная с Cython 0.11, модуль pyximport также имеет экспериментальную поддержку компиляции для обычных модулей Python ...» подразумевает, что в нем все еще есть некоторые проблемы, над которыми нужно работать. Вы тоже можете это объяснить?
Нуб Сайбот
1
По поводу «экспериментальной поддержки компиляции для обычных модулей Python» - с кодом, который я предложил выше, .pyмодули компилируются нормально (не с помощью cython), а .pyxмодули компилируются с помощью cython. Если вы перейдете pyimport = Trueв pyximport.install(), тогда он будет использовать cython для всего, даже например import randomили import os. Я не предлагаю использовать эту функцию просто потому, что нет веских причин для ее использования, и это может создать проблемы. Вероятно, он используется в основном разработчиками cython.
Стив Бирнс
Если он pyximportвообще работает, он создаст тот же код C, что и любой другой метод. Так что попробуйте и убедитесь. Я имел в виду тот факт, что когда процесс компиляции достаточно сложен, например, ссылки на внешние системные библиотеки, вы можете обнаружить, что pyximport не работает, и вам понадобится setup.pyи, cythonizeчтобы точно указать, как его построить. Но тот факт, что ваш .pyxмодуль имеет imports или cimports, не означает, что он не может быть скомпилирован pyximport; это вполне может быть совершенно нормально.
Стив Бирнс
У меня есть сообщение Cython, о котором вы, возможно, сможете рассказать.
Филипп
14

Ошибка означает, что файл заголовка numpy не найден во время компиляции.

Попробуй сделать export CFLAGS=-I/usr/lib/python2.7/site-packages/numpy/core/include/, а потом скомпилировать. Это проблема нескольких разных пакетов. В ArchLinux есть ошибка по той же проблеме: https://bugs.archlinux.org/task/22326

Джон Броди
источник
Куда добавить exportстрочку? В моем setup.pyфайле?
Нуб Сайбот
Нет, это команда оболочки. Запустите его в своей оболочке, затем начните компиляцию.
Джон Броди
@NoobSaibot в оболочке (где вы запускаете python setup.py) export ..сначала запустите команду. Он устанавливает переменные окружения оболочки, но не имеет ничего общего с [pc] ython.
tacaswell
@tcaswell: Я так и думал. Я использую cmd и получаю эту 'export' is not recognized as an internal or external command, operable program or batch file.ошибку ... просто не могу победить с этим ...
Нуб Сайбот
4
@NoobSaibot, вы получаете ответы на lunix о том, что пахнет проблемой Windows ....
tacaswell
1

Простой ответ

Более простой способ - добавить путь к вашему файлу 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
strpeter
источник
1

Если вам лень писать установочные файлы и выяснять путь для включаемых каталогов, попробуйте cyper . Он может скомпилировать ваш код Cython и include_dirsавтоматически установить для Numpy.

Загрузите свой код в строку, затем просто запустите 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

Вы можете установить cyper через pip install cyper.

Сиртис Майор
источник